%lf
- это double
, а не единичная точность float
. И нет, 2 аргумента, которые вы передаете scanf: double *
, , а не double
, поэтому вы должны установить AL=0
не 2
.
В любом случае, ваша проблемаявляется то, что вы передали один и тот же указатель для обоих выходных операндов. И это scanf
уничтожает свои регистры передачи аргументов, как это позволяет соглашение о вызовах. ( Какие регистры сохраняются посредством вызова функции linux x86-64 )
Эквивалент C похож на scanf("%lf %lf", &b, &b)
после резервирования стекового пространства для 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.
фиктивный push / pop обычно стоит только (вместо add rsp, imm8
) для one слот стека, и в основном, если вы собираетесь сразу же call
вместо явной ссылки на RSP. После этого будет выполнена синхронизация стека.