以下是我用C编写的小程序.
#include <stdio.h>
int main(int argc, char const *argv[])
{
int i;
for (i = 0; i < 10; i++) {
puts("Hello World!");
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
以下是gdb测试:
(gdb) break main
Breakpoint 1 at 0x40050f: file main.c, line 7.
(gdb) run
Breakpoint 1, main (argc=1, argv=0x7fffffffe708) at main.c:7
7 for (i = 0; i < 10; i++) {
(gdb) disassemble main
Dump of assembler code for function main:
0x0000000000400500 <+0>: push rbp
0x0000000000400501 <+1>: mov rbp,rsp
0x0000000000400504 <+4>: sub rsp,0x20
0x0000000000400508 <+8>: mov DWORD PTR [rbp-0x14],edi
0x000000000040050b <+11>: mov QWORD PTR [rbp-0x20],rsi
=> 0x000000000040050f <+15>: mov DWORD PTR [rbp-0x4],0x0
0x0000000000400516 <+22>: jmp 0x400526 <main+38>
0x0000000000400518 <+24>: mov edi,0x4005c4
0x000000000040051d <+29>: call 0x4003e0 <puts@plt>
0x0000000000400522 <+34>: add DWORD PTR [rbp-0x4],0x1
0x0000000000400526 <+38>: cmp DWORD PTR [rbp-0x4],0x9
0x000000000040052a <+42>: jle 0x400518 <main+24>
0x000000000040052c <+44>: mov eax,0x0
---Type <return> to continue, or q <return> to quit---
0x0000000000400531 <+49>: leave
0x0000000000400532 <+50>: ret
End of assembler dump.
Run Code Online (Sandbox Code Playgroud)
以下部分是我不理解的事情.请注意$ rip是"指令指针"并指向 0x000000000040050f <+15>
(gdb) x/x $rip
0x40050f <main+15>: 0x00fc45c7
(gdb) x/12x $rip
0x40050f <main+15>: 0x00fc45c7 0xeb000000 0x05c4bf0e 0xbee80040
0x40051f <main+31>: 0x83fffffe 0x8301fc45 0x7e09fc7d 0x0000b8ec
0x40052f <main+47>: 0xc3c90000 0x1f0f2e66 0x00000084 0x1f0f0000
(gdb) x/8xb $rip
0x40050f <main+15>: 0xc7 0x45 0xfc 0x00 0x00 0x00 0x00 0xeb
(gdb) x/8xh $rip
0x40050f <main+15>: 0x45c7 0x00fc 0x0000 0xeb00 0xbf0e 0x05c4 0x0040 0xbee8
(gdb) x/8xw $rip
0x40050f <main+15>: 0x00fc45c7 0xeb000000 0x05c4bf0e 0xbee80040
0x40051f <main+31>: 0x83fffffe 0x8301fc45 0x7e09fc7d 0x0000b8ec
Run Code Online (Sandbox Code Playgroud)
第一个命令x/x $rip输出0x40050f <main+15>: 0x00fc45c7.
它是0x40050f的指令吗?是0x00fc45c7一样的mov DWORD PTR [rbp-0x4],0x0(在0x40050f装配指令)?
其次,如果是指令,什么是从命令的输出的十六进制数字x/12x $rip,x/8xw $rip,x/8xh $rip?
至于(1),你得到了正确的答案.
对于(2),x命令最多有3个说明符:要打印的对象数量; 以哪种格式; 什么对象大小.在所有示例中,您选择以十六进制(x)打印.对于第一个说明符,您要求打印12,8,8个对象.
对于你的情况中的最后一个说明符:
x/12x没有,所以gdb默认假设你想要双字,也就是4字节块.请注意,您发现双字有时定义不同,但在intel x86汇编/ gdb中,它是4个字节.一般来说,我总是指定你想要什么,而不是回到默认设置.
对于8个对象,x/8xw执行相同操作,因为您现在明确请求了dwords.
x/8xh请求半字大小的字节块,因此以2字节块的形式打印对象.如果你想知道为什么两个相邻值的串联不等于什么报道,当你在双字印刷,这是因为x86是小端架构.这意味着在erickson的书中再次详细说明 - 如果你看几页,他会做一些你可能会觉得有用的计算.简而言之,如果你重新组合它们(2,1)(4,3),......,你会发现它们匹配.
(gdb) help x
Examine memory: x/FMT ADDRESS.
ADDRESS is an expression for the memory address to examine.
FMT is a repeat count followed by a format letter and a size letter.
Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal),
t(binary), f(float), a(address), i(instruction), c(char) and s(string),
T(OSType), A(floating point values in hex).
Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes).
The specified number of objects of the specified size are printed
according to the format.
Defaults for format and size letters are those previously used.
Default count is 1. Default address is following last thing printed
with this command or "print".
Run Code Online (Sandbox Code Playgroud)