我一直在深入研究 Linux 和 C,我很好奇函数是如何存储在内存中的。我有以下功能:
void test(){
printf( "test\n" );
}
很简单。当我在具有此功能的可执行文件上运行 objdump 时,我得到以下信息:
08048464 <test>:
8048464: 55 push %ebp
8048465: 89 e5 mov %esp,%ebp
8048467: 83 ec 18 sub $0x18,%esp
804846a: b8 20 86 04 08 mov $0x8048620,%eax
804846f: 89 04 24 mov %eax,(%esp)
8048472: e8 11 ff ff ff call 8048388 <printf@plt>
8048477: c9 leave
8048478: c3 ret
这一切看起来都不错。有趣的部分是当我运行以下代码时:
int main( void ) {
char data[20];
int i;
memset( data, 0, sizeof( data ) );
memcpy( data, test, 20 * sizeof( char ) );
for( i = 0; i < 20; ++i ) {
printf( "%x\n", data[i] );
}
return 0;
}
我得到以下信息(这是不正确的):
55
ffffff89
ffffffe5
ffffff83
ffffffec
18
ffffffc7
4
24
10
ffffff86
4
8
ffffffe8
22
ffffffff
ffffffff
ffffffff
ffffffc9
ffffffc3
如果我选择省略 memset(data, 0, sizeof(data)); 行,则最右边的字节是正确的,但其中一些仍然具有前导 1。
有没有人解释为什么
A)使用 memset 清除我的数组会导致函数的不正确(编辑:不准确)表示,并且
解决方案:是由于使用了 memset(data, 0, sizeof(data)),而不是 memset(data, 0, 20 * sizeof(unsigned char))。内存没有完全设置,因为它只查看指针的大小而不是整个数组的大小。
B)这个字节存储在内存中是什么?整数?字符?我不太明白这里发生了什么。(澄清:我将使用什么类型的指针来遍历内存中的此类数据?)
解决方案:我很笨。我忘记了 unsigned 关键字,这就是整个问题的来源:(
任何帮助将不胜感激 - 我在四处搜索时找不到任何东西。
尼尔
PS:我的直接想法是,这是 x86 的指令不以字节或半字节边界结束的结果。但这并没有多大意义,也不应该引起任何问题。
感谢 Will 指出我的 char 类型错误。它应该是无符号字符。但是,我仍然对如何访问单个字节感到好奇。