我是一名使用Java和C几年的程序员,最近我正在阅读高级C和C ++编译这本书,我从中了解到在调用main之前调用了一些函数,喜欢" _start"," __ libc_start_main"。这些细节必须由C专家在这里解释和回答数百次。
但是我注意到一些非常微小的东西,使用C语言中的常见函数调用约定,比如cdecl,当我们编写一个函数时,它的名字将以下划线为前缀' _'编译完毕后。这意味着如果你有一个名为foo的函数,它将在最终的汇编文本中编译为_foo。相反,如果我们在汇编文本中找到一个名为_start的节,它应该有一个名为" start"的映射函数。在C.
我是对的吗?如果是这样," __ libc_start_main"在汇编文本中应该将其函数签名为" _libc_start_main" (C中少一个下划线前缀)?
080482d0 <_start>:
80482d0: 31 ed xor %ebp,%ebp
80482d2: 5e pop %esi
80482d3: 89 e1 mov %esp,%ecx
80482d5: 83 e4 f0 and $0xfffffff0,%esp
80482d8: 50 push %eax
80482d9: 54 push %esp
80482da: 52 push %edx
80482db: 68 50 84 04 08 push $0x8048450
80482e0: 68 e0 83 04 08 push $0x80483e0
80482e5: 51 push %ecx
80482e6: 56 push %esi
80482e7: 68 d0 83 04 08 push $0x80483d0
80482ec: e8 cf ff ff ff call 80482c0 <__libc_start_main@plt>
80482f1: f4 hlt
80482f2: 66 90 xchg %ax,%ax
我知道这显然不对,因为如果你google它,数百个网站会告诉你它的签名与标记和在程序集中调用完全相同。任何C专家都能解释一下吗?
int __libc_start_main(
int (*main)(int, char **, char **), int argc, char **argv,
int (*init)(int, char **, char **), void (*fini)(void),
void (*ldso_fini)(void)) ;