您的位置:首页 > 移动开发

A Minimal Application in Assembly:不要迷信洋人

2010-04-02 22:32 204 查看
在PC Ubuntu下,我用汇编能写的最小应用程序为:

.text

.globl _start

__start:

mov $1, %eax /* __NR_exit, see /usr/include/asm/unistd_32.h */

mov $0, %ebx /* exit status */

int $0x80 /* _exit */

用gcc编译后生成的程序是600字节。

$ gcc -O3 -nostdlib min.s -o min

$ wc -c min

600 min

当然,这个min程序一无用处,运行时什么都没作,直接退出。退出的状态0,返回给其父进程。

$ ./min;echo $?

0

但就是这样一个应用,老外也能玩出花样,http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html

上介绍如何把可执行程序压榨到45字节。Gee! 这种本来应该是日本人拿手的,怎么白人也喜欢小的?

另外,Jeff Duntemann在其“Assembly Language Step by Step Programming with Linux"一书 Page 242声称:

The _start label indicates where the program begins. Every Linux assembly language program has to be marked this way, and with the precise label _start. (It’s case sensitive, so don’t try using _START or _Start.) Furthermore, this label must be marked as global at the top of the .text section, as shown. This is a requirement of the Linux operating system. Every executable program for Linux has to have a label _start in it somewhere, irrespective of the language it’s written in: C, Pascal, assembly, no matter.

这说法是有问题的。我来说两句:

1。 The _start label indicates where the program begins

OK,基本正确,但是不是100%。参照我后面从GNU拷贝过来的linker说明。

2。Every Linux assembly language program has to be marked this way, and
with the precise label _start. (It’s case sensitive, so don’t try using
_START or _Start.)

Wrong。参照我后面从GNU拷贝过来的linker说明。

3。 This is a requirement of the Linux operating system

Wrong。是linker要根据_start符号来决定程序的执行入口点,然后写到可执行文件的ELF header中。kernel根据ELF header找到entry point,kernel根本不不要知道_start。

4。Every Linux assembly language program has to be marked this way, and with the precise label _start.

Wrong。参照我后面从GNU拷贝过来的linker说明。

GNU linker文档对程序的执行入口点有如下说明:

3.4.1 Setting the entry point

The first instruction to execute in a program is called the entry point

. You can use the
ENTRY


linker script command to set the entry point. The argument is a symbol name:
ENTRY(symbol
)

There are several ways to set the entry point. The linker will set the entry point by trying each of the following methods in order, and stopping when one of them succeeds:

the `-e'

entry

command-line option;

the
ENTRY(symbol

)


command in a linker script;

the value of the symbol
start


, if defined;

the address of the first byte of the `.text'

section, if present;

The address
0


.

我们代码验证上述第一种情况,用begin代替_start。

$ cat begin.s

.text

.globl begin

begin:

mov $1, %eax /* syscall no, see /usr/include/asm/unistd_32.h */

mov $0, %ebx /* exit status */

int $0x80 /* _exit */

$ gcc -nostdlib -Wl,-entry=begin begin.s -o begin

$ ./begin;echo $?

0

果然没有任何问题。

结论:我们不要迷信洋人的书。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐