根据标准调用约定,argv中的参数存储在寄存器rsi中。
假设我的argc是2,命令行如下:
./program a
我想比较是否等于“ a”。 我有以下代码:
mov r12, rsi
mov r13, 0
mov r14, qword[r12+r13*8]
cmp r14, "a"
je Success
; Code here that displays error
Success:
; etc.
所以,我不确定自己在做什么错,但是它并不能成功,但是应该正确吗?
我将不胜感激。
答案 0 :(得分:1)
a
将是argv[1]
,但是您正在加载argv[0]
(按照惯例,程序名,但是如果您的程序是用{{调用的,则可以是NULL指针或任意字符串) 1}},而不是普通外壳。execve()
与指针值进行比较,而不是与指向的字符串数据进行比较。即您编写的C版本是
"a"
对于汇编时间常数索引,应该只使用位移而不是索引寄存器。您可以使用if( (intptr_t)argv[0] == "a" ){
success:
}
或1 * 8
之类的汇编时表达式,以一种对人类看起来不错的方式编写它。
0 * 8
global main
main:
cmp edi, 2
jb too_few_args ; if(argc<2) avoid segfaults in both of the next 2 insns
mov rdx, [rsi + 8*1] ; r14 = argv[1]
cmp byte [rdx], "a" ; argv[1][0] == 'a'
je success
...
success:
xor eax,eax
ret ; return 0
是x86-64 System V ABI中的一个保留呼叫的寄存器,因此,如果您的r14
返回而不是main
,则应保留R14相同的值进入时。 What registers are preserved through a linux x86-64 function call
RDX是呼叫密集型的,因此它是临时寄存器的不错选择。
它还保存了一个代码大小的字节以使用RDX或其他一些不需要REX前缀而不是R8..15的暂存寄存器。 qword call exit
将始终需要REX前缀,而字节mov
则不需要。