问题描述
像这样的简单代码
#include<stdio.h>
int main()
{
return 0;
}
用gdb检查“&main”中的值,我得到0xe5894855,我想知道这是什么吗?
(gdb) x/x &main
0x401550 <main>: 0xe5894855
(gdb)
解决方法
(gdb) x/x &main
0x401550 <main>: 0xe5894855
(gdb)
0xe5894855
是main中第一条指令的十六进制操作码,但是由于您使用了x/x
,现在gdb
将其显示为十六进制数字,并且由于x86-64被显示而向后小端。 55
是push rbp
的操作码和main
的第一条指令。使用x/i &main
查看说明。
用gdb检查“&main”中的值,我得到0xe5894855,我想知道这是什么吗?
C表达式&main
的值是指向(函数)main
的指针。
gdb命令
x/x &main
以十六进制格式(&main
)打印(eXamines)存储在/x
表示的地址中的值。在您的情况下,结果为0xe5894855
,但C语言未指定该值的重要性。实际上,即使从程序内部读取C,C也没有定义任何严格符合的方式。
在实践中,该值可能代表函数机器码的前四个字节,按原始字节顺序解释为四字节无符号整数。但这取决于实现细节,涉及C实现的两个GDB。
,好吧,0x401550
是main()的地址,右边的十六进制是该地址的“内容”,这没有多大意义,因为它的代码存储在这里,而不是数据。
要解释十六进制粘胶的来源,我们可以举一些人工的例子:
#include <stdio.h>
int main (void)
{
printf("%llx\n",(unsigned long long)&main);
}
在gcc x86_64上运行此代码,我得到401040
,这是我特定系统上main()的地址(这次)。然后,将示例修改为丑陋的硬编码:
#include <stdio.h>
int main (void)
{
printf("%llx\n",(unsigned long long)&main);
printf("%.8x\n",*(unsigned int*)0x401040);
}
(请注意,像这样访问程序代码存储器的绝对地址是很脏的黑客行为。这是非常可疑的做法,如果尝试,某些系统可能会抛出硬件异常。)
我明白了
401040
08ec8348
乱七八糟的第二行类似于gdb所提供的内容:存储在那里的指令的原始操作代码。
(也就是说,它实际上是一个程序,该程序会打印出用于打印机器代码的机器代码...现在我的头很痛...)
反汇编并生成可执行文件的二进制文件,然后使用带注释的汇编查看数字操作码,我得到:
main:
48 83 ec 08
401040 sub rsp,0x8
其中48 83 ec 08
是原始机器代码,包括带有其参数的指令sub
(x86汇编器并不是我的强项,但我相信48是"REX prefix",而83是sub
的操作码)。尝试将其打印为好像是整数数据而不是机器代码时,它会按照从48 83 ec 08
到08 ec 83 48
的x86小尾数顺序进行处理。这就是以前的十六进制08ec8348
。