将argv中的第一个参数与char比较

时间:2018-10-13 00:34:46

标签: assembly x86-64

根据标准调用约定,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.

所以,我不确定自己在做什么错,但是它并不能成功,但是应该正确吗?

我将不胜感激。

1 个答案:

答案 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则不需要。