原文鏈接:http://www.orlion.ga/989/
一、匯編程序的Hello world
x86 AT&T:
.data msg: .ascii "Hello world, hello AT&T asm!\n" len = . - msg .text .global _start _start: movl $len, %edx # 顯示的字符數 movl $msg, %ecx # 緩沖區指針 movl $1, %ebx # 文件描述符 movl $4, %eax # 系統調用號,_write int $0x80 # 系統調用 movl $0, %ebx # 傳給_exit的參數 movl $1, %eax # 系統調用號,_exit int $0x80 # 系統調用
然后匯編鏈接再執行:

這段匯編相當於:
#include <unistd.h>
char msg[14] = "Hello,world!\n";
#define len 14
int main(void)
{
write(1, msg, len);
_exit(0);
}
.data段有一個標號msg,代表字符串“Hello,world!\n”的首地址,相當於C程序的一個全局變量。在匯編指示.ascii定義的字符串末尾沒有隱含的‘\0’。匯編程序中的len代表一個常量,它的值由當前地址減去符號msg所代表的地址得到,換句話說就是字符串“Hello,world!\n”的長度。現在解釋一下這行代碼中的.,匯編器總是從前到后把匯編代碼轉換成目標文件,在這個過程中維護一個地址計數器,當處理到每個段的開頭時把地址計數器置成0,然后每處理一條匯編指示或指令就把地址計數器增加相應的字節數,在匯編程序中用.可以取出當前地址計數器的值,是一個常量。
在_start中調了兩個系統調用,第一個是write系統調用,第二個是以前講過的_exit系統調用。在調write系統調用時,eax寄存器保存着write的系統調用號4,ebx、ecx、edx寄存器分別保存着write系統調用需要三個參數。ebx保存着文件描述符,進程中每個打開的文件都用一個編號來標識,成為文件描述符,文件描述符1表示標准輸出,對應的C標准I/O庫的stdout。ecx保存着輸出緩沖區的首地址。edx保存着輸出的字節數。write系統調用把從msg開始的len個字節寫到標准輸出。
C代碼中的write函數是系統調用的包裝函數,其內部實現就是把傳進來的三個參數分別賦給ebx、ecx、edx寄存器,然后執行movl $4,%eax和int $0x80兩指令。這個函數不可能完全用C代碼寫,因為任何C代碼都不會編譯生成int指令,所以這個函數有可能完全用匯編寫的,也有可能是C用內聯匯編寫的,甚至是一個宏定義。_exite函數野史如此。
