我正在浏览一本关于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.lst
gcc -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 0001111x/qx &qNum3
期望的值接近0x 4048 F5 C3 x/qx &qNum3
将输出结果0x 51 eb 851 fprint /f &qNum3
期望的值接近3.14 print /f &qNum3
将输出“$2 = 2.0803755547161745e-317”
如果先运行x/bu &bNum
命令,则先前的检查命令现在将输出与以前不同的结果。
命令x/qf &qNum3
将输出预期结果3.14x/qt &qNum3
现在将输出结果00011111x/qx &qNum3
现在将输出结果0x 1f
1条答案
按热度按时间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字节的块x
,x /f
也可以工作。这就是为什么x /b
(Byte)会从后面不包括大小的x
命令中更改结果。)您还可以执行
p (double[3])qNum1
来将所有3个qword解释为IEEE二进制64位模式(NASM源代码中的前两个是整数,其位模式表示微小的双精度)。