Compiler construction x64双打的比较
我正在编写一个玩具编译器,但我对double的比较结果并不像预期的那样。编译器应该输出x64 nasm汇编程序。 编译器还没有进行任何优化,因此此时生成的代码可能“不确定”。在保留错误的同时,我已经把它清理得足够干净了 我的系统中的双精度应该适合64位。此时,编译器为它们分配了16个字节,但如果我理解正确,这不会干扰这些指令。如果是这样的话,请告诉我代码应该进行计算(1.01325==1.01325) 要在linux计算机上像这样运行代码,请执行以下操作:Compiler construction x64双打的比较,compiler-construction,comparison,64-bit,Compiler Construction,Comparison,64 Bit,我正在编写一个玩具编译器,但我对double的比较结果并不像预期的那样。编译器应该输出x64 nasm汇编程序。 编译器还没有进行任何优化,因此此时生成的代码可能“不确定”。在保留错误的同时,我已经把它清理得足够干净了 我的系统中的双精度应该适合64位。此时,编译器为它们分配了16个字节,但如果我理解正确,这不会干扰这些指令。如果是这样的话,请告诉我代码应该进行计算(1.01325==1.01325) 要在linux计算机上像这样运行代码,请执行以下操作: nasm -f elf64 -file
nasm -f elf64 -file.asm-
clang -o test runtime.o -file.o-
源代码中存在一些常量
segment .data
str1 dq 0.0
str2 dq 101325.0
str3 dq 101325.0
首先,代码通常在输入时运行
segment .text
global main
main:
push qword rbp ; save rbp
mov qword rbp, rsp ; load rsp
我把一个常数放在分配给变量v0的空间中。然后我将这个值和另一个常量(本例中相同)推送到FP堆栈上
sub rsp, 16 ; reserve space for v0
mov qword [rbp-16], str2
fld qword [rbp-16] ; push v0
fld qword [str3] ; push str3
然后使用fcomi
比较它们,然后弹出FP堆栈的两个操作数。然后,如果它们相等,我希望分支(我也尝试使用jz
,产生相同的结果)
编译器现在只根据跳转将'true'或'false'加载到rax
寄存器
var4: ; emit false
mov qword rax, 0
jmp var5
var3: ; emit true
mov qword rax, 1
var5: ; end of ==
现在,根据rax
中的值,如果两个双精度值是==
,则代码再次分支它应该分支到var1,因为常数明显相等,但它不。有人能给我指出正确的方向吗
cmp qword rax, 1 ; if ((101325.0 double)== (v0 double)boolean)
jz var1
var0: ; else
jmp var2
var1: ; then
; do stuff
; commented out
var2:
mov qword rax, 0 ; return 0
mov qword rsp, rbp ; restore sp
pop rbp ; restore fp
ret ; pop & jump
可能是我假设我的系统使用“其他”endian格式吗?请让我知道,如果有任何额外的信息,我应该提供,或者如果我可以提高我的职位在任何方式的质量
谢谢
编辑:
根据要求,这里是生成的完整代码。最后执行的返回1
是在我的设置中打印的,但是我还必须发布我使用的运行时
[BITS 64]
extern readInt
extern readDouble
extern printInt
extern printString
extern printDouble
segment .data
str1 dq 0.0
str2 dq 101325.0
str3 dq 101325.0
segment .text
global main
main:
push qword rbp ; save rbp
mov qword rbp, rsp ; load rsp
sub rsp, 16 ; reserve space for v0
mov qword [rbp-16], str2
fld qword [rbp-16] ; push v0
fld qword [str3] ; push str3
fcomi st1 ; compare ST0 and ST1
fstp st0 ; pop ST0
fstp st0 ; pop ST0
je var3 ; jump if ==
var4: ; emit false
mov qword rax, 0
jmp var5
var3: ; emit true
mov qword rax, 1
var5: ; end of ==
cmp qword rax, 1 ; if ((101325.0 double)== (v0 double)boolean)
jz var1
var0: ; else
jmp var2
var1: ; then
mov qword rax, 1 ; return 1
var2:
mov qword rax, 0 ; return 0
mov qword rsp, rbp ; restore sp
pop rbp ; restore fp
ret ; pop & jump
我已经用nemiver调试了你的代码。 错误在这一行:
mov qword [rbp-16], str2
它不会将str2(101325.0)的值移动到[rbp-16],而是移动str2的地址。
我是这样修复的:
mov qword rax, [str2]
mov qword [rbp-16], rax
然后,它会像预期的那样一直持续到var1。您是否尝试了JNZ而不是JE?因为这会设置ZF标志@TarunLalwani No,因为我想这会做相反的事情?据我所知,
fcomi
基本上执行st0-st1
,并根据结果设置标志。如果ZF=1
,则数字相等,je
或jz
应该做我想做的事情。我的推理有误吗?你能附上完整的asm文件吗?@TarunLalwani我现在发布了全部内容。你必须使用调试器,你会看到发生了什么。你会遇到类似的问题,如果没有调试器,你会无能为力。这是肯定的,我忽略了这个潜在的问题。非常感谢,我将在将来查看nemiver。
mov qword rax, [str2]
mov qword [rbp-16], rax