说我在(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 *
,not double
,因此您应该将AL=0
设置为2
。
无论如何,您的问题是您为两个输出操作数传递了相同的指针。 并且那个scanf
破坏了它的arg传递寄存器,就像调用约定允许的那样。(What registers are preserved through a linux x86-64 function call)
为scanf("%lf %lf", &b, &b)
保留堆栈空间后,C等效项类似于double a,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.
对于[[one堆栈插槽,通常仅使用[[虚拟推入/弹出](而不是add rsp, imm8
),然后如果您要立即进入call
而不是明确引用RSP,则通常才值得。这样做将插入堆栈同步uop。