理解Linux命令行参数在栈中的分配
事情的起源是,我和这个博文的作者遇到了同一个问题。
这个血案我就不重述了,请见这里:http://blog.chinaunix.net/uid-24774106-id-2783020.html
该博文认为,《Professional Assembly Language》里面对Linux命令行参数在栈中的分配的描述是错的。
确实,用gcc编译书中的代码,是得不到想要的结果的。但问题不是书中说错了。而是我们编译方式不对。
使用gas编译和使用gcc编译汇编有个不同的地方,就是beginning execution entry point ,gas(即as命令)要求是.global _start,而gcc要求是.global main。
为什么有这个区别呢?
事实上ld命令是可以自己指定entry point的 (ld -emain),这样,不就可以将gcc和ld as的使用统一了吗?
当然不是的。使用gcc编译,entry point指定为main的原因在于,gcc会自己加一个_start,然后在_start里调用你的main。通过下面的代码测试下就知道了。
.section .data hello: .asciz "Hello,world!\n".section .text.global mainmain: push $hello call printf push $0 call exit
gcc gcctest.s -o gcctest.bin -g
$ gdb gcctest.bin Reading symbols from /data/code/asm/learn/linux/gcctest.bin...done.(gdb) disass _startDump of assembler code for function _start: 0x08048360 <+0>: xor %ebp,%ebp 0x08048362 <+2>: pop %esi 0x08048363 <+3>: mov %esp,%ecx 0x08048365 <+5>: and $0xfffffff0,%esp 0x08048368 <+8>: push %eax 0x08048369 <+9>: push %esp 0x0804836a <+10>: push %edx 0x0804836b <+11>: push $0x80484a0 0x08048370 <+16>: push $0x8048430 0x08048375 <+21>: push %ecx 0x08048376 <+22>: push %esi 0x08048377 <+23>: push $0x8048414 0x0804837c <+28>: call 0x8048350 <__libc_start_main@plt>(gdb) disass mainDump of assembler code for function main: 0x08048414 <+0>: push $0x804a018 0x08048419 <+5>: call 0x8048320 <printf@plt> 0x0804841e <+10>: push $0x0 0x08048420 <+12>: call 0x8048340 <exit@plt>
gcc gcctest.s -o gcctest.bin -g -nostartfiles