我有一个简单的C代码:
#include <stdio.h>
void p(){
printf("jjjj");
}
int main(){
p();
}
如果我在Mac OSX上使用g ++编译并使用otool -tv
进行反汇编,我可以看到p
和main
函数以及main
调用p
。使用优化(-O3
)我得到了这个:
(__TEXT,__text) section
__Z1pv:
0000000100000f40 pushq %rbp
0000000100000f41 movq %rsp, %rbp
0000000100000f44 leaq 0x4b(%rip), %rdi
0000000100000f4b xorl %eax, %eax
0000000100000f4d popq %rbp
0000000100000f4e jmp 0x100000f76
0000000100000f53 nopw %cs:(%rax,%rax)
_main:
0000000100000f60 pushq %rbp
0000000100000f61 movq %rsp, %rbp
0000000100000f64 leaq 0x2b(%rip), %rdi
0000000100000f6b xorl %eax, %eax
0000000100000f6d callq 0x100000f76
0000000100000f72 xorl %eax, %eax
0000000100000f74 popq %rbp
0000000100000f75 retq
似乎main
仍在地址0x100000f76
处调用某些内容。我如何查看这个位置的内容? g++
在这做什么?
答案 0 :(得分:3)
您没有将p()
声明为static
,因此您看到的是p()
的编译版本,该版本调用printf()
(通过jmp
),然后您还在p()
内获得main()
的内联版本,该版本也会转换为对printf()
的调用。如果您将p()
声明为static
,那么您只会在main()
中看到内联电话。
要回答您的问题,0x100000f76
似乎是printf()
的入口点。
告诉编译器生成asm,而不是解散代码,你可能会觉得更有帮助,因为这将包含更多有用的信息,例如: gcc -S -O3
(在OS X上使用clang)生成:
.section __TEXT,__text,regular,pure_instructions
.macosx_version_min 10, 11
.globl _p
.align 4, 0x90
_p: ## @p
.cfi_startproc
## BB#0:
pushq %rbp
Ltmp0:
.cfi_def_cfa_offset 16
Ltmp1:
.cfi_offset %rbp, -16
movq %rsp, %rbp
Ltmp2:
.cfi_def_cfa_register %rbp
leaq L_.str(%rip), %rdi
xorl %eax, %eax
popq %rbp
jmp _printf ## TAILCALL
.cfi_endproc
.globl _main
.align 4, 0x90
_main: ## @main
.cfi_startproc
## BB#0:
pushq %rbp
Ltmp3:
.cfi_def_cfa_offset 16
Ltmp4:
.cfi_offset %rbp, -16
movq %rsp, %rbp
Ltmp5:
.cfi_def_cfa_register %rbp
leaq L_.str(%rip), %rdi
xorl %eax, %eax
callq _printf
xorl %eax, %eax
popq %rbp
retq
.cfi_endproc
.section __TEXT,__cstring,cstring_literals
L_.str: ## @.str
.asciz "jjjj"
.subsections_via_symbols
在这里,您可以看到jmp
和callq
到printf
,而不仅仅是某个未知地址。