问题
I had written a simple c program and was trying to do use GDB to debug the program. I understand the use of following in main function:
On entry
push %ebp
mov %esp,%ebp
On exit
leave
ret
Then I tried gdb on _start and I got the following
xor %ebp,%ebp
pop %esi
mov %esp,%ecx
and $0xfffffff0,%esp
push %eax
push %esp
push %edx
push $0x80484d0
push $0x8048470
push %ecx
push %esi
push $0x8048414
call 0x8048328 <__libc_start_main@plt>
hlt
nop
nop
nop
nop
I am unable to understand these lines, and the logic behind this.
Can someone provide any guidance to help explain the code of _start
?
回答1:
Here is the well commented assembly source of the code you posted.
Summarized, it does the following things:
- establish a sentinel stack frame with ebp = 0 so code that walks the stack can find its end easily
- Pop the number of command line arguments into
esi
so we can pass them to__libc_start_main
- Align the stack pointer to a multiple of 16 bits in order to comply with the ABI. This is not guaranteed to be the case in some versions of Linux so it has to be done manually just in case.
- The addresses of
__libc_csu_fini
,__libc_csu_init
, the argument vector, the number of arguments and the address ofmain
are pushed as arguments to__libc_start_main
__libc_start_main
is called. This function (source code here) sets up some glibc-internal variables and eventually callsmain
. It never returns.- If for any reason
__libc_start_main
should return, ahlt
instruction is placed afterwards. This instruction is not allowed in user code and should cause the program to crash (hopefully). - The final series of
nop
instructions is padding inserted by the assembler so the next function starts at a multiple of 16 bytes for better performance. It is never reached in normal execution.
回答2:
for gnu tools the _start label is the entry point of the program. for the C language to work you need to have a stack you need to have some memory/variables zeroed and some set to the values you chose:
int x = 5;
int y;
int fun ( void )
{
static int z;
}
all three of these variables x,y,z are essentially global, one is a local global. since we wrote it that way we assume that when our program starts x contains the value 5 and it is assumed that y is zero. in order for those things to happen, some bootstrap code is required and that is what happens (and more) between _start and main().
Other toolchains may choose to use a different label to define the entry/start point, but gnu tools use _start. there may be other things your tools require before main() is called C++ for example requires more than C.
来源:https://stackoverflow.com/questions/35519417/understanding-assembly-language-start-label-in-a-c-program