假设我在(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
调用约定,但还没有找到明确的答案。
%lf
是double
,而不是单精度float
。不,传递给scanf的2个参数是double *
,而不是double
,所以应该设置AL=0
而不是2
。
无论如何,您的问题是为两个输出操作数传递了相同的指针并且scanf
破坏其arg传递寄存器,就像调用约定允许的那样。(通过linux x86-64函数调用保留哪些寄存器(
在为double a,b;
保留堆栈空间之后,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.
对于一个堆栈插槽,伪推送/弹出通常只值得(而不是add rsp, imm8
(,然后主要是如果您要立即使用call
而不是显式引用RSP。这样做将插入一个堆栈同步uop。