前面20篇汇编学习笔记主要是学习《深入理解计算机系统》过程中所记录的笔记,接下来打算学一下另外一本书《Assembly Language step by step programming with linux》。
首先需要安装NASM汇编器,例如:
rpm –ivh nasm-2.10-1.i386.rpm
《Assembly Language step by step programming with linux》书中的第一个汇编程序叫eatsyscall,我把它改写成一个HelloWorld小程序。
SECTION .data ; Section containing initialised data
HelloMsg:db "Hello World!",10
HelloLen:equ $-HelloMsg
SECTION .bss ; Section containing uninitialized data
SECTION .text ; Section containing code
global _start ; Linker needs this tofind the entry point!
_start:
nop ; This no-op keeps gdbhappy...
mov eax,4 ; Specify sys_writecall
mov ebx,1 ; Specify FileDescriptor 1: Standard Output
mov ecx,HelloMsg ; Pass offset ofthe message
mov edx,HelloLen ; Pass the lengthof the message
int 80H ; Make kernelcall
mov eax,1 ; Code for ExitSyscall
mov ebx,0 ; Return a code ofzero
int 80H ; Make kernelcall
程序的英文注释已经解释的很清楚了:程序共做了两个系统调用(int 0x80),eax寄存器保存系统调用号,系统调用号4表示sys_write,系统调用号1表示sys_exit。
对于sys_write,共有3个传入参数,分别保存在寄存器ebx,ecx和edx中。ebx保存的是文件描述符,1表示标准输出。ecx保存的是消息字符串的地址,edx保存的是消息字符串的长度。
对于sys_exit系统调用,只有一个传入参数,表示程序的退出码,ebx保存0,就是说退出码是0。
HelloMsg: db "Hello World!",10
HelloMsg是在数据段(.data)中定义的字符串标号,db表示define byte。也就是说HelloMsg表示一个字节数组,10是换行符(\n)的ASCII码值。
HelloLen:equ $-HelloMsg
HelloLen是字符串长度的标号,equ表示等同于,$是一个指示当前位置的变量,表示HelloMsg字节数组的最后一个字节后面的那个字节的位置,$减去HelloMsg(字符串数组的第一个字节的位置),得到的恰好是字节数组的长度,这个长度值由汇编器在编译时计算得到。
使用如下makefile文件来生成程序:
helloworld: helloworld.o
ld -m elf_i386 -o helloworld helloworld.o
helloworld.o: helloworld.asm
nasm -f elf32 -g -F stabs helloworld.asm -l helloworld.lst
-f elf32:生成elf32格式的目标文件。
-g:生成调试信息。
-F stabs:生成STABS格式的调试信息。
[root@bogon helloworld]# make
nasm -f elf32 -g -F stabs helloworld.asm -lhelloworld.lst
ld -o helloworld helloworld.o
[root@bogon helloworld]# ./helloworld
Hello World!