如何在汇编中访问 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
调用约定,但尚未找到明确的答案。
%lf
是 double
,不是单精度 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。
假设我用 (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
破坏了它的参数传递寄存器,就像调用约定允许的那样。 (What registers are preserved through a linux x86-64 function call)
在为 double a,b;
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。