Assembly NASM协处理器-未获得预期输出

Assembly NASM协处理器-未获得预期输出,assembly,nasm,x86-64,libc,x87,Assembly,Nasm,X86 64,Libc,X87,我正在编写一个简单的程序,其中我应该得到前两个命令行参数,它们是整数,然后对它们执行一些操作。但我有个问题。当我想打印出这些操作的结果时,我只得到0.00,我不知道为什么 section .data first dq 0 second dq 0 fp db '%.2f ' section .bss sqr1 resq 1 sqr2 resq 1 divRes resq 1 section .text extern printf global main main: push rbp mov

我正在编写一个简单的程序,其中我应该得到前两个命令行参数,它们是整数,然后对它们执行一些操作。但我有个问题。当我想打印出这些操作的结果时,我只得到
0.00
,我不知道为什么

section .data
first dq 0
second dq 0
fp db '%.2f '

section .bss
sqr1 resq 1
sqr2 resq 1
divRes resq 1

section .text
extern printf 
global main

main:
push rbp
mov rbp, rsp
push rbx
push rsi
push rdi

mov rdi, [rsi+8]
mov rcx, 0
mov rax, 0
readFirst:
mov byte al, [rdi+rcx]
cmp al, 0
je next1
sub al, 30h
push rax
inc rcx
jmp readFirst

next1:
mov rdx, 10
mov rbx, 1
atoi1:
pop rax
mul bl
add [first], ax
mov rax, rbx
mul dl
mov rbx, rax
loop atoi1

mov rcx, 0
mov rax, 0
mov rdi, [rsi+16]
readSecond:
mov byte al, [rdi+rcx]
cmp al, 0
je next2
sub al, 30h
push rax
inc rcx
jmp readSecond

next2:
mov rdx, 10
mov rbx, 1
atoi2:
pop rax
mul bl
add [second], ax
mov rax, rbx
mul dl
mov rbx, rax
loop atoi2

fild qword[first]
fsqrt
fstp qword[sqr1]

mov rax, 0
mov rdi, fp
mov rsi, [sqr1]
call printf

fild qword[second]
fsqrt
fstp qword[sqr2]

mov rax, 0
mov rdi, fp
mov rsi, [sqr2]
call printf

fild qword[first]
fild qword[second]
fdivp
fstp qword[divRes]

mov rax, 0
mov rdi, fp
mov rsi, [divRes]
call printf


pop rdi
pop rsi
pop rbx
mov rsp, rbp
pop rbp
ret

我测试了参数,它们被正确地存储在内存中。似乎问题出在协处理器指令中。

打印浮点数时,不能仅使用普通x86寄存器(rdi、rsi、rdx、rcx、r9、r8)发送浮点参数。 有xmm寄存器,它们被索引为xmm0..7。 您需要做的是将要打印的浮点移动到xmm0、xmm1。。。 使用“movsd”指令而不是正常的mov指令 并移动到通过xmm寄存器发送的参数数rax。 然后你可以调用printf

mov rdi,fp
mov rax,1
movsd xmm0 qword[divres]
call printf

这应该可以工作

因为您使用64位x86处理器,而不使用SSE(SIMD)的任何原因SQRTSD等指令?其次,您是否使用GDB或其他调试器加载此代码,并在每条指令中查看寄存器和内存,然后按照代码流程了解可能出错的地方?我不认为问题在于实际的
fsqrt
或保存到内存的代码。问题是您错误地混合了32位浮点(标量)、64位双精度(双精度标量)和整数。很明显,您的代码首先读取的是整数,您将它们加载到x87中并执行sqrt,但将双精度(64位)保存回内存。那很好。但是使用GCC时,需要使用
%Lf
作为双精度格式。然后,您会遇到一个问题,浮点和双精度必须在SSE寄存器中传递。第一个double/float在XMM0中不是RDIDoh,您使用的格式说明符是正确的,对不起。将其保持为
%.2f
,因为浮点数会自动升级为双精度浮点数(使用诸如printd之类的可变函数),所以
%lf
将默认打印双精度浮点数。谢谢!这样一个简单的修复程序,现在就可以使用了。您可能想重新访问这个
movsd qword[divres]