歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Unix知識 >> 關於Unix >> Linux匯編語言開發指南(二)

Linux匯編語言開發指南(二)

日期:2017/3/6 15:22:27   编辑:關於Unix
接(一) MI LY: "> _start: # 在屏幕上顯示一個字符串 movl len, %edx # 參數三:字符串長度 movl msg, %ecx # 參數二:要顯示的字符串 movl , %ebx # 參數一:文件描述符 (s td out) movl , %eax # 系統調用號 (sys_write) int x80 # 調用內核功能 # 退出程序 接(一)

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,它提供了很好的宏指令功能,並能夠支持相當多的目標代碼格式,包括 bina.outcoffelfrdf 等。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 下調試匯編代碼既可以用 GDBDDD 這類通用的調試器,也可以使用專門用來調試匯編代碼的 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 0.1.3
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 BA0F000000 mov edx, 0xf
08048079 B998900408 mov ecx, 0x8049098
0804807E BB01000000 mov ebx, 0x1
08048083 B804000000 mov eax, 0x4
08048088 CD80 int 0x80
0804808A BB00000000 mov ebx, 0x0
0804808F B801000000 mov eax, 0x1

Copyright © Linux教程網 All Rights Reserved