我是x86_64编码的新手,正在探索各种代码。
我正在尝试比较nasm x86_64代码中的字符"a",但比较结果不相等。
; Tests the command line. Similar to a C main function:
; int main(int argc, char** argv)
;
; - argc, number of args in rdi
; - argv, pointer to pointer in rsi and argv
global main
extern puts
main:
mov rbp, rdi ; argc in rdi. Save in rbp, caller-saved
mov rbx, rsi ; argv in rsi. Save in rbx, caller-saved
add rbx, 8
dec rbp
mov rdi, [rbx]
cmp rdi, 'A'
je exit1
call puts
mov rax, 0
ret
exit1:
mov rax, 1
ret
如何修改代码以获得所需的结果?有一些解决方案,但它使用了8位寄存器,正如这里所用的那样,比较汇编、nasm中的字符,但为了澄清我的基本知识,我想了解为什么像我的代码这样的直接比较不起作用。
-
argv
是指向以null结尾的字符串的指针列表的指针。在顶部,您必须首先取消引用指针mov rbx, [rsi]
,这样您实际上是在检查*char
值的列表。 -
引用英特尔关于
cmp
:的指令参考,cmp
操作数的大小(实际上对于几乎所有指令(都很重要当立即数用作操作数时,它会被符号扩展到第一个操作数的长度。
您实际上是在比较两个64位数量。
-
(至少(有两种可能的解决方案:
cmp dil, 'A'
:您仍然可以一次从内存中检索8个字节,但为了进行比较,您需要指定一个部分寄存器- 在
cmp
之前插入movsx rdi, dil
(或与一步movsx rdi, byte [rbx]
中的fetch组合(:正如Jester所建议的,您仍然可以执行64位比较,但要确保高位设置正确
-
写入
cmp rdi, 'A'
是写入cmp rdi, 0x41
的替代方案。在执行时,0x41
得到符号扩展,因此您最终将0x00000041
与rdi
的内容进行比较。现在,如果您以前从[rbx]
加载八个字节,则上面的七个字节可能会填充有胡言乱语,或者说,char
字符串中后面的字符。这会给你带来麻烦。 -
旁注:说到参数传递,我不确定是否可以这样调用
puts
。rdi
不应该包含以null结尾的字符串的地址吗?