Compiler construction x64双打的比较

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

我正在编写一个玩具编译器,但我对double的比较结果并不像预期的那样。编译器应该输出x64 nasm汇编程序。 编译器还没有进行任何优化,因此此时生成的代码可能“不确定”。在保留错误的同时,我已经把它清理得足够干净了

我的系统中的双精度应该适合64位。此时,编译器为它们分配了16个字节,但如果我理解正确,这不会干扰这些指令。如果是这样的话,请告诉我代码应该进行计算(1.01325==1.01325)

要在linux计算机上像这样运行代码,请执行以下操作:

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