x86_64汇编实现strcmp为何出现相等判断顺序相关异常?
x86_64汇编实现strcmp的返回值比较异常问题
问题现象
用x86_64汇编实现简易版my_strcmp后,与C库原生strcmp对比出现以下异常:
- 两者返回值打印结果看似一致(例如均为-11)
- 条件
(strcmp(s1,s2) == my_strcmp(s1,s2))判断为假,而my_strcmp(s1,s2) == strcmp(s1,s2)却为真 - 用C语言实现相同逻辑的版本无此问题
编译步骤与输出差异
编译命令
nasm -f elf64 -g my_strcmp.s -o my_strcmp_assembly.o gcc -c my_strcmp.c gcc main.c my_strcmp.o -o c_version.out gcc main.c my_strcmp_assembly.o -o asm_version.out ./c_version.out && ./asm_version.out
输出对比
C版实现(符合预期)
a == b strcmp return value is -11 ft_strcmp retun value is -11 OK1 OK2
汇编版实现
a == b strcmp return value is -11 ft_strcmp retun value is -11 OK2
使用环境:gcc 11.4.0、nasm 2.15.05
问题根源
这是因为汇编实现未遵循x86_64 System V ABI的返回值约定:
- C标准库的
strcmp返回int类型(32位有符号整数),会自动符号扩展到64位的rax寄存器中(例如-11的64位表示为0xfffffffffffffff5)。 - 你的汇编实现仅将字符差值存入8位的
al寄存器就直接返回,未将其符号扩展到整个64位rax,导致rax的高56位保留了随机垃圾值(例如差值-11的8位是0xf5,若高位为0则rax值为0x00000000000000f5,即十进制245)。 - 这种不符合约定的返回值触发了C语言的未定义行为,导致比较顺序不同时结果异常。
解决方案
在汇编代码中,计算出字符差值后,使用cdqe指令将8位差值符号扩展到整个64位rax寄存器,确保返回值符合ABI约定。
示例修正后的核心汇编逻辑:
global my_strcmp my_strcmp: ; rdi = s1, rsi = s2 .loop: mov al, byte [rdi] cmp al, byte [rsi] jne .diff test al, al je .equal inc rdi inc rsi jmp .loop .diff: sub al, byte [rsi] ; 计算s1[i] - s2[i] cdqe ; 将8位有符号数扩展到64位rax ret .equal: xor eax, eax ; 返回0,自动扩展到rax ret
内容的提问来源于stack exchange,提问作者aLeuleu
相关产品推荐
相关产品推荐

