如何在汇编中访问 scanf 调用的第一个参数?

How to Access First Parameter of scanf Call in Assembly?

假设我用 (AT&T) 程序集编写了以下代码:

push qword 0
push qword 0
mov rax, 2                ;Tell rax we receive 2 floats
mov rdi, floatformat      ;floatformat db "%lf %lf",0

mov rsi, rsp              ;I am assuming my logic flaw is in these two lines
mov rdx, rsp

call scanf
pop rax                   ;Clean up the stack
pop rax

movsd xmm0, [rsi]         ;This does not give the value I want

如上面的评论所述,我希望 xmm0 保留用户在执行 call scanf 时输入的第一个浮点数,但只接收第二个浮点数。我知道这很可能是由于 mov rdx, rsp 操作造成的,但如果未执行该操作,我的程序将无法正确运行以读取用户输入。

如何获得用户输入的第一个浮动?我已经尝试研究 scanf 调用约定,但尚未找到明确的答案。

%lfdouble,不是单精度 float。不,您传递给 scanf 的 2 个参数是 double * 而不是 double,因此您应该设置 AL=0 而不是 2.

无论如何,您的问题是您为两个输出操作数传递了相同的指针。 并且 scanf 破坏了它的参数传递寄存器,就像调用约定允许的那样。 (What registers are preserved through a linux x86-64 function call)

在为 double a,b;

保留堆栈 space 之后,C 等效项类似于 scanf("%lf %lf", &b, &b)
    ; assuming stack is 16-byte aligned to start with,
    ; e.g. if your function started with an odd number of pushes

    sub   rsp, 16
    mov   rsi, rsp        ; pointer to low slot
    lea   rdx, [rsp+8]    ; pointer to high slot
    lea   rdi, [rel format_string]    ; use RIP-relative LEA for 64-bit static addresses
    xor   eax,eax         ; 0 FP args in regs to a variadic function
    call  scanf           ; scanf(fmt, &tmp0, &tmp1)

    movaps xmm0, [rsp]     ; load both doubles
    add    rsp, 16         ; now tmp0 and tmp1 are below RSP, in the red-zone

    movsd   xmm1, [rsp-8]  ; or shuffle xmm0 to get tmp1 from the high half.

dummy push/pop 通常只值得(而不是 add rsp, imm8)用于 one 堆栈槽,然后主要是如果你要 call 立即而不是明确引用 RSP。这样做会插入一个堆栈同步 uop。