一起學習在linux下使用匯編語言(5)
2024-07-21 02:37:18
供稿:網友
作者:luster
摘要:好吧,我們已經鋪墊了很多東西了,而且看上去用匯編寫程序似乎是一個非常恐怖的事情了。不過既然我們感愛好,還是應該開始我們的“hello world”程序。
5. 我們開始寫hello world吧
好吧,我們已經鋪墊了很多東西了,而且看上去用匯編寫程序似乎是一個非常恐怖的事情了。不過既然我們感愛好,還是應該開始我們的“hello world”程序。
下面的代碼中,我們預備采取直接使用內核中的系統(tǒng)調用的方法,這是調用系統(tǒng)內核服務的最快的方法,我們的代碼不鏈接到其他函數庫,也不使用ELF解釋器,而是直接和內核通訊。
我們分別使用nasm和gas兩種匯編器來編譯我們的程序,這樣我們可以看到Intel和AT&T兩種語法格式了。
使用的工具
當然首先我們需要匯編編譯器nasm和gas。然后我們需要鏈接器-ld,因為匯編編譯器是生成的只是object代碼。一般的發(fā)行包的binutils里面包括了gas和ld這兩個實用工具。而對于大多數的發(fā)行包(例如,Debian,SuSe,Mandrake)都有nasm。
Hello, world!
linux是一個32位的,運行在保護模式下的操作系統(tǒng),使用的是flat memory 模式,使用ELF格式的二進制代碼。
一個程序可以劃分為下面幾個部分: .text,.data,.bss。.text是一些只讀的代碼,.data是可讀可寫的數據區(qū),.bss則是可讀可寫的沒有初始化的數據區(qū)。當然可以有其他一些標準的部分,也可以使用戶自己定義的sections,但是我們這里不關心。一個程序至少有.text部分。
下面就是我們的第一個程序“hello,world”。我們給出兩個版本,分別是nasm和gas兩種。
NASM (hello.asm)
--------------
section .data ;section declarationmsg db "Hello, world!",
0xa ;our dear stringlen equ $ - msg ;length of our dear stringsection .text ;
section declaration ;we must eXPort the entry point to the ELF linker
or global _start ;loader. They conventionally recognize _start as their ;
entry point. Use ld -e foo to override the default._start:;write our string
to stdout mov edx,len ;third argument: message length mov ecx,msg ;second
argument: pointer to message to write mov ebx,1 ;first argument: file handle
(stdout) mov eax,4 ;system call number (sys_write) int 0x80 ;call kernel;
and exit mov ebx,0 ;first syscall argument: exit code mov eax,1 ;system
call number (sys_exit) int 0x80 ;
call kernel
GAS (hello.S)
--------------
.data # section declarationmsg: .string "Hello, world! "
# our dear string len = . - msg # length of our dear string.text
# section declaration # we must export the entry point to the ELF linker or
.global _start # loader. They conventionally recognize _start as their
# entry point. Use ld -e foo to override the default._start:
# write our string to stdout movl $len,%edx # third argument:
message length movl $msg,%ecx # second argument: pointer to message to
write movl $1,%ebx # first argument: file handle (stdout) movl $4,%eax
# system call number (sys_write) int $0x80 # call kernel# and exit movl
$0,%ebx # first argument: exit code movl $1,%eax # system call number
(sys_exit) int $0x80 # call kernel
建立可運行的程序
要生成一個可執(zhí)行的代碼,首先就是用源代碼編譯生產一個object文件。
對于nasm,下面的語法:
$ nasm -f elf hello.asm
而對于gas,而用下面的語法:
$ as -o hello.o hello.S
這樣就得到了hello.o這個object文件了。
然后我們就要使用這個object文件來生成可執(zhí)行代碼。這里使用鏈接器鏈接:
$ ld -s -o hello hello.o
這樣我們就獲得了我們的可以執(zhí)行的代碼“hello,world”。
我們的學習就告一段落了。更多的信息可以去參考:
http://linuxassembly.org/list
by Luster(luster@linuxaid.com.cn)