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

本文探讨了在Linux环境下使用汇编语言编写最小的应用程序,并详细分析了程序入口点的设置方式,纠正了一些关于_start标签的误解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

在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

 

果然没有任何问题。

 

结论:我们不要迷信洋人的书。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值