MILY: ˎ̥">_start: # 在屏幕上顯示一個字符串
movl $len, %edx # 參數三:字符串長度
movl $msg, %ecx # 參數二:要顯示的字符串
movl , %ebx # 參數一:文件描述符(stdout)
movl , %eax # 系統調用號(sys_write)
int x80 # 調用內核功能
# 退出程序
movl ,%ebx # 參數一:退出代碼
movl ,%eax # 系統調用號(sys_exit)
int x80 # 調用內核功能
初次接觸到 AT&T 格式的匯編代碼時,很多程序員都認為太晦澀難懂了,沒有關系,在 Linux 平台上你同樣可以使用 Intel 格式來編寫匯編程序:
例2. Intel 格式
; hello.asm
section .data ; 數據段聲明
msg db "Hello, world!", 0xA ; 要輸出的字符串
len equ $ - msg ; 字串長度
section .text ; 代碼段聲明
global _start ; 指定入口函數
_start: ; 在屏幕上顯示一個字符串
mov edx, len ; 參數三:字符串長度
mov ecx, msg ; 參數二:要顯示的字符串
mov ebx, 1 ; 參數一:文件描述符(stdout)
mov eax, 4 ; 系統調用號(sys_write)
int 0x80 ; 調用內核功能
; 退出程序
mov ebx, 0 ; 參數一:退出代碼
mov eax, 1 ; 系統調用號(sys_exit)
int 0x80 ; 調用內核功能
上面兩個匯編程序采用的語法雖然完全不同,但功能卻都是調用 Linux 內核提供的 sys_write 來顯示一個字符串,然後再調用 sys_exit 退出程序。在 Linux 內核源文件 include/asm-i386/unistd.h 中,可以找到所有系統調用的定義。
四、Linux 匯編工具
Linux 平台下的匯編工具雖然種類很多,但同 DOS/Windows 一樣,最基本的仍然是匯編器、連接器和調試器。
1.匯編器
匯編器(assembler)的作用是將用匯編語言編寫的源程序轉換成二進制形式的目標代碼。Linux 平台的標准匯編器是 GAS,它是 GCC 所依賴的後台匯編工具,通常包含在 binutils 軟件包中。GAS 使用標准的 AT&T 匯編語法,可以用來匯編用 AT&T 格式編寫的程序:
[xiaowp@gary code]$ as -o hello.o hello.s
Linux 平台上另一個經常用到的匯編器是 NASM,它提供了很好的宏指令功能,並能夠支持相當多的目標代碼格式,包括 bin、a.out、coff、elf、rdf 等。NASM 采用的是人工編寫的語法分析器,因而執行速度要比 GAS 快很多,更重要的是它使用的是 Intel 匯編語法,可以用來編譯用 Intel 語法格式編寫的匯編程序:
[xiaowp@gary code]$ nasm -f elf hello.asm
2.鏈接器
由匯編器產生的目標代碼是不能直接在計算機上運行的,它必須經過鏈接器的處理才能生成可執行代碼。鏈接器通常用來將多個目標代碼連接成一個可執行代碼,這樣可以先將整個程序分成幾個模塊來單獨開發,然後才將它們組合(鏈接)成一個應用程序。 Linux 使用 ld 作為標准的鏈接程序,它同樣也包含在 binutils 軟件包中。匯編程序在成功通過 GAS 或 NASM 的編譯並生成目標代碼後,就可以使用 ld 將其鏈接成可執行程序了:
[xiaowp@gary code]$ ld -s -o hello hello.o
3.調試器
有人說程序不是編出來而是調出來的,足見調試在軟件開發中的重要作用,在用匯編語言編寫程序時尤其如此。Linux 下調試匯編代碼既可以用 GDB、DDD 這類通用的調試器,也可以使用專門用來調試匯編代碼的 ALD(Assembly Language Debugger)。
從調試的角度來看,使用 GAS 的好處是可以在生成的目標代碼中包含符號表(symbol table),這樣就可以使用 GDB 和 DDD 來進行源碼級的調試了。要在生成的可執行程序中包含符號表,可以采用下面的方式進行編譯和鏈接:
[xiaowp@gary code]$ as --gstabs -o hello.o hello.s
[xiaowp@gary code]$ ld -o hello hello.o
執行 as 命令時帶上參數 --gstabs 可以告訴匯編器在生成的目標代碼中加上符號表,同時需要注意的是,在用 ld 命令進行鏈接時不要加上 -s 參數,否則目標代碼中的符號表在鏈接時將被刪去。
在 GDB 和 DDD 中調試匯編代碼和調試 C 語言代碼是一樣的,你可以通過設置斷點來中斷程序的運行,查看變量和寄存器的當前值,並可以對代碼進行單步跟蹤。
圖1 用 DDD 中調試匯編程序
匯編程序員通常面對的都是一些比較苛刻的軟硬件環境,短小精悍的ALD可能更能符合實際的需要,因此下面主要介紹一下如何用ALD來調試匯編程序。首先在命令行方式下執行ald命令來啟動調試器,該命令的參數是將要被調試的可執行程序:
[xiaowp@gary doc]$ ald hello
Assembly Language Debugger
Copyright (C) 2000-2002 Patrick Alken
hello: ELF Intel 80386 (32 bit), LSB, Executable, Version 1 (current)
Loading debugging symbols...(15 symbols loaded)
ald>
當 ALD 的提示符出現之後,用 disassemble 命令對代碼段進行反匯編:
ald> disassemble -s .text
Disassembling section .text (0x08048074 - 0x08048096)
08048074 BA
08048079 B998900408 mov ecx, 0x8049098
0804807E BB01000000 mov ebx, 0x1
08048083 B804000000 mov eax, 0x4
08048088 CD80 int 0x80