这个简单的问候世界:
#include <stdio.h>
int main(void) {
printf("Hello, world!\n");
printf("Hello, world!\n");
return 0;
}
在objdump中提供以下程序集:
/helloworld.c:3 804842c: 83 ec 0c sub $0xc,%esp 804842f: 68 f0 84 04 08 push $0x80484f0 8048434: e8 b7 fe ff ff call 80482f0 8048439: 83 c4 10 add $0x10,%esp /helloworld.c:4 804843c: 83 ec 0c sub $0xc,%esp 804843f: 68 f0 84 04 08 push $0x80484f0 8048444: e8 a7 fe ff ff call 80482f0 8048449: 83 c4 10 add $0x10,%esp
答案 0 :(得分:1)
call rel32
指令:调用near,相对于下一条指令的位移
此指令的操作码为E8
,后跟由以下等式计算的相对偏移量:destination address - address of next instruction
。
在这种情况下,第一个呼叫的相对偏移量为80482f0 - 8048439 = FFFFFEB7
,第二个呼叫的相对偏移量为80482f0 - 8048449 = FFFFFEA7
。
答案 1 :(得分:1)
E8
操作码属于CALL
指令,其地址相对于CALL
指令本身的地址。它使用PC relative addressing
。因此,您所看到的函数地址实际上是从下一条指令的地址到printf
函数起始地址的偏移量。
顺便说一句,英特尔使用小端,因此必须将这些偏移分别读为带符号的32位整数FFFFFEB7
和FFFEA7
。这意味着printf
函数位于相对于主程序的较低地址。
您还可以看到,这两个偏移的差异是从一个CALL
指令到另一个指令的字节差异,因为第二个CALL
将距离{{1}的开头更远比第一个。
printf