linux 参数栈地址出错,懂得Linux命令行参数在栈中的分配

理解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 main

main:

push $hello

call printf

push $0

call exit

使用gcc编译

gcc gcctest.s -o gcctest.bin -g

使用gdb看结果

$ gdb gcctest.bin

Reading symbols from /data/code/asm/learn/linux/gcctest.bin...done.

(gdb) disass _start

Dump of assembler code for function _start:

0x08048360 : xor %ebp,%ebp

0x08048362 : pop %esi

0x08048363 : mov %esp,%ecx

0x08048365 : and $0xfffffff0,%esp

0x08048368 : push %eax

0x08048369 : push %esp

0x0804836a : push %edx

0x0804836b : push $0x80484a0

0x08048370 : push $0x8048430

0x08048375 : push %ecx

0x08048376 : push %esi

0x08048377 : push $0x8048414

0x0804837c : call 0x8048350 <__libc_start_main>

(gdb) disass main

Dump of assembler code for function main:

0x08048414 : push $0x804a018

0x08048419 : call 0x8048320

0x0804841e : push $0x0

0x08048420 : call 0x8048340

可以看到。gcc添加的自己的_start,做了很多其它的工作。最后,调用main时,已经将棧修改成像C语言中main接收参数时的样子了,也就是argc和argv[],envp[]。所以,原文作者测试时发现棧中的结果会是那个样子。

相同的程序,将entry改成_start,并用as汇编,ld链接,则结果就是正确的。

事实上,gcc也可以通过参数,设置不加载它自己的startfiles

gcc gcctest.s -o gcctest.bin -g -nostartfiles

-nostartfiles参数

Do not use the standard system startup files when linking.  The standard system libraries are used normally, unless -nostdlib or -nodefaultlibs is used.

至于这个startfiles倒底做了哪些工作(比如加载动态链接库),我没有细细分析。

反正结论就是,原书作者是对的,只是因为我们用了gcc编译器,这真是一个大坑。

还有个大坑是,gcc说它支持intel_syntax,事实上呢?别提啦,更别提.att_syntax noprefix了。老实的写att_syntax,每个register都加个%前缀吧。

坑爹的汇编语言啊

1 楼

zjhlht

2012-11-09

有用!收藏一下

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值