0

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

所以,我不确定我做错了什么,但它并没有成功,但它应该是对的?

我将不胜感激任何帮助。

4

1 回答 1

1
  • 您使用比必要的更多说明使这变得过于复杂
  • a将是argv[1],但您正在加载(按照惯例,程序名称,但如果您的程序是从普通 shell 以外的其他东西argv[0]调用的,则可能是 NULL 指针或任意字符串)。execve()
  • 您正在"a"与指针值进行比较,而不是与指向的字符串数据进行比较。

即你写的C版本是

if( (intptr_t)argv[0] == "a" ){
    success:
}

对于汇编时间常数索引,您应该只使用位移而不是索引寄存器。1 * 8您可以使用诸如or之类的汇编时表达式以适合人类的方式编写它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

r14是 x86-64 System V ABI 中的调用保留寄存器,因此如果您main返回而不是call exit,您应该将 R14 保留为与输入时相同的值。 通过 linux x86-64 函数调用保留了哪些寄存器

RDX 是 call-clobbered,因此它是暂存器的不错选择。

它还节省了一个字节的代码大小以使用 RDX 或其他不需要 REX 前缀而不是 R8..15 的暂存寄存器。qwordmov总是需要一个 REX 前缀,但字节cmp不需要。

于 2018-10-13T12:48:08.067 回答