assembly gdb print和examine命令给予不正确的浮点变量结果

b1zrtrql  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(100)

我正在浏览一本关于x64汇编的书。这本书描述了一点如何使用gdb,我能够检查整数,但是print不起作用。如果我使用像这样的examine,x/bu &bNum,它将输出123,那么examine将对整数起作用,比如“db”。
对于一个浮点值,如果我在检查一个浮点值之前没有检查一个整数,我将得到一个我认为是错误的结果。运行x/qf &qNum3将输出结果1.26443839e+11
如果我使用x/bu &bNum,然后运行x/qf &qNum3,它将给予预期的结果3.1400000000001那么,为什么检查浮点数给予正确的输出只有在检查整数之后?
使用前面的任何命令而不使用"&“导致gdb响应“'qNum 3' has unknown type; cast it to it's declared type“这是预期的响应吗?
印刷品似乎总是不能给予正确的结果。
我正在使用下面的命令,正如书中所指示的,为了汇编和链接程序nasm -f elf64 -g -F dwarf move.asm -l move.lstgcc -o move move.o -no-pie
这是书中给出的一个示例程序。

; move.asm
section .data
      bNum  db    123
      wNum  dw    12345
      dNum  dd    1234567890
      qNum1 dq    1234567890123456789
      qNum2 dq    123456
      qNum3 dq    3.14
section .bss
section .text
      global main
main:
push  rbp
mov   rbp,rsp
      mov rax, -1           ; fill rax with 1s
      mov al, byte [bNum]   ; does NOT clear upper bits of rax
      xor rax,rax           ; clear rax
      mov al, byte [bNum]   ; now rax has the correct value
      mov rax, -1           ; fill rax with 1s
      mov ax, word [wNum]   ; does NOT clear upper bits of rax
      xor rax,rax           ; clear rax
      mov ax, word [wNum]   ; now rax has the correct value
      mov rax, -1           ; fill rax with 1s
      mov eax, dword [dNum] ; does clear upper bits of rax
      mov rax, -1           ; fill rax with 1s
      mov rax, qword [qNum1] ; does clear upper bits of rax
      mov qword [qNum2], rax ; one operand always a register
      mov rax, 123456       ; source operand an immediate value
      movq xmm0, [qNum3]    ; instruction for floating point
mov rsp,rbp
pop rbp
ret

字符串
x/qf &qNum3期望的值接近3.14 x/qf &qNum3将输出结果“<0x404027>1.26443839e+11”
x/qt &qNum3期望的值接近01000000 01001000 11110101 11000011 x/qt &qNum3将输出结果01010001 11101011 10000101 0001111
x/qx &qNum3期望的值接近0x 4048 F5 C3 x/qx &qNum3将输出结果0x 51 eb 851 f
print /f &qNum3期望的值接近3.14 print /f &qNum3将输出“$2 = 2.0803755547161745e-317”
如果先运行x/bu &bNum命令,则先前的检查命令现在将输出与以前不同的结果。
命令x/qf &qNum3将输出预期结果3.14
x/qt &qNum3现在将输出结果00011111
x/qx &qNum3现在将输出结果0x 1f

djmepvbi

djmepvbi1#

/q不是GDB的大小修饰符。根据h x,8字节大小为/g(Giant)。

x /gf &qNum3正确地将内存作为8字节的双精度数,

p (double)qNum3也是如此。print /f &qNum3将地址解释为浮点位模式,与print (double)&qNum3相同的结果,一个微小的低于正常的浮点数(只有一些位设置在尾数的底部附近)。
GDB强制转换使用C语法,但它们类似于std::bit_cast,告诉它如何解释位,而不是以不同的类型产生表示相同数字的新值。(至少对于变量,而不是像print (double)1234这样的常量。)
我不知道/q作为/x的修饰符有什么作用,但由于大小仍然是默认的32位,因此您将尾数的低4个字节解释为float(IEEE二进制32),与从p (float)qNum3获得的数字相同
x会记住你最后使用的大小,所以如果你以前使用过8字节的块xx /f也可以工作。这就是为什么x /b(Byte)会从后面不包括大小的x命令中更改结果。)
您还可以执行p (double[3])qNum1来将所有3个qword解释为IEEE二进制64位模式(NASM源代码中的前两个是整数,其位模式表示微小的双精度)。

相关问题