彙編語言編寫的Hello World

Linux 下用匯編語言編寫的代碼具有兩種不同的形式。第一種是完全的彙編代碼,指的是整個程序全部用匯編語言編寫。儘管是完全的彙編代碼,Linux 平臺下的彙編工具也吸收了 C 語言的長處,使得程序員可以使用 #include、#ifdef 等預處理指令,並能夠通過宏定義來簡化代碼。第二種是內嵌的彙編代碼,指的是可以嵌入到C語言程序中的彙編代碼片段。雖然 ANSI 的 C 語言標準中沒有關於內嵌彙編代碼的相應規定,但各種實際使用的 C 編譯器都做了這方面的擴充,這其中當然就包括 Linux 平臺下的 GCC。

一 Linux彙編語法格式

絕大多數 Linux 程序員以前只接觸過DOS/Windows 下的彙編語言,這些彙編代碼都是 Intel 風格的。但在 Unix 和 Linux 系統中,更多采用的還是 AT&T 格式,兩者在語法格式上有着很大的不同.

二 Hello World的編寫

在 Linux 操作系統中,你有很多辦法可以實現在屏幕上顯示一個字符串,但最簡潔的方式是使用 Linux 內核提供的系統調用。使用這種方法最大的好處是可以直接和操作系統的內核進行通訊,不需要鏈接諸如 libc 這樣的函數庫,也不需要使用 ELF 解釋器,因而代碼尺寸小且執行速度快。
Linux 是一個運行在保護模式下的 32 位操作系統,採用 flat memory 模式,目前最常用到的是 ELF 格式的二進制代碼。一個 ELF 格式的可執行程序通常劃分爲如下幾個部分:.text、.data 和 .bss,其中 .text 是隻讀的代碼區,.data 是可讀可寫的數據區,而 .bss 則是可讀可寫且沒有初始化的數據區。代碼區和數據區在 ELF 中統稱爲 section,根據實際需要你可以使用其它標準的 section,也可以添加自定義 section,但一個 ELF 可執行程序至少應該有一個 .text 部分。 下面給出我們的第一個彙編程序,用的是 AT&T 彙編語言格式:

例:AT&T格式

#hello.s 
.data                    # 數據段聲明
        msg : .string "Hello, world!\\n" # 要輸出的字符串
        len = . - msg                   # 字串長度
.text                    # 代碼段聲明
.global _start           # 指定入口函數

_start:                  # 在屏幕上顯示一個字符串
        movl $len, %edx  # 參數三:字符串長度
        movl $msg, %ecx  # 參數二:要顯示的字符串
        movl $1, %ebx    # 參數一:文件描述符(stdout) 
        movl $4, %eax    # 系統調用號(sys_write) 
        int  $0x80       # 調用內核功能

                         # 退出程序
        movl $0,%ebx     # 參數一:退出代碼
        movl $1,%eax     # 系統調用號(sys_exit) 
        int  $0x80       # 調用內核功能

例: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 彙編工具

1.彙編器
彙編器(assembler)的作用是將用匯編語言編寫的源程序轉換成二進制形式的目標代碼。Linux 平臺的標準彙編器是 GAS,它是 GCC 所依賴的後臺彙編工具,通常包含在 binutils 軟件包中。GAS 使用標準的 AT&T 彙編語法,可以用來彙編用 AT&T 格式編寫的程序:

panlu@ThinkPad:~/彙編語言$ as -o hello.o helloWorld.s

Linux 平臺上另一個經常用到的彙編器是 NASM,它提供了很好的宏指令功能,並能夠支持相當多的目標代碼格式,包括 bin、a.out、coff、elf、rdf 等。NASM 採用的是人工編寫的語法分析器,因而執行速度要比 GAS 快很多,更重要的是它使用的是 Intel 彙編語法,可以用來編譯用 Intel 語法格式編寫的彙編程序:

panlu@ThinkPad:~/彙編語言$ nasm -f elf hello.asm

2.鏈接器
由彙編器產生的目標代碼是不能直接在計算機上運行的,它必須經過鏈接器的處理才能生成可執行代碼。鏈接器通常用來將多個目標代碼連接成一個可執行代碼,這樣可以先將整個程序分成幾個模塊來單獨開發,然後纔將它們組合(鏈接)成一個應用程序。 Linux 使用 ld 作爲標準的鏈接程序,它同樣也包含在 binutils 軟件包中。彙編程序在成功通過 GAS 或 NASM 的編譯並生成目標代碼後,就可以使用 ld 將其鏈接成可執行程序了:

panlu@ThinkPad:~/彙編語言$ ld -s -o hello hello.o

3 運行

panlu@ThinkPad:~/彙編語言$ ./hello
Hello World!

四 Intel格式

1、在ubuntu上安裝nasm方法

首先在網站http://www.nasm.us/pub/nasm/releasebuilds/2.10.07/下面去下載2.10.07.tar.gz這個版本(一般在ubuntu上面都是使用這個壓縮形式的)。如果要下其他版本的nasm可以通過http://www.nasm.us/來進行選擇進行下載。

2、安裝方法:使用如下的命令:

解壓:tar zxvf nasm-2.10.07.tar.gz

進入剛解壓的目錄 cd 解壓後的目錄

然後執行命令:./configure
make
sudo make install

通過以上的步驟nasm就在ubuntu上安裝好了。也可以通過使用命令:nasm -version來查看是否安裝成功。如果出現了nasm的版本信息則說明安裝成功,否則還需進一步安裝。

panlu@ThinkPad:~/彙編語言$ nasm -version
NASM version 2.10.07 compiled on Sep 29 2015

3 編譯運行

nasm -f elf64(elf32) hello.asm (注意這裏使用elf64還是elf32要看操作系統的位數來決定)
gcc -o hello hello.o
./hello

輸出Hello World便成功了.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章