在汇编语言学习中找到的一个很好的入门Tutorial,所以摘录了一些比较重要的要点
1.一个汇编语言程序一般可分成3部分:
1) .data 区
用来定义初始化变量 (但是此处的这些变量定义后在程序执行过程中是不允许改变的,所以是狭隘意义上的“变量”)
从C 语言的角度来说,这些宏,导入声明文件库等都应该在这块区域内。 这里可以使用EQU,DB, DW, DD, DQ 和 DT 等其他指令操作
section .data
message: db 'Hello world!' ; 定义“变量” message,值为 'Hello world!' (不包含单引号)
msglength: equ 12 ; 定义变量“msglength” 值为12
buffersize: dw 1024 ; 定义变量“buffersize”,数据类型为字,值为 1024
2) .bss 区
此区域定义所有的变量, 可以使用 RESB, RESW, RESD, RESQ 和 REST 等指令操作在内存中申请为初始化的空间。
filename: resb 255 ; 申请 255 bytes
number: resb 1 ; 申请 1 byte
bignum: resw 1 ; 申请 1 word (1 word = 2 bytes)
realarray: resq 10 ; 申请一个包含 10 个(reals)实数数组
3) .text 区
汇编语言的所有操作定义在此区域。 .text 开头必须定义 global _start ,来告诉内核该程序的入口在哪里(类似于C或Java中的main函数,区别是它并不是一个函数,而只是一个起始点)
section .text
global _start
_start:
pop ebx ; 这是程序的起始处
.
.
.
2. 调用Linux的内核
Linux系统内核调用方式跟DOS是一样的。
1. 将内核调用代码写进 EAX (这里以32位系统为例)
2. 将内核调用所需要的参数写进 EBX, ECX 等
3. 调用系统内核终止指令 (DOS是21h,而Linux则是80h)
4. 内核调用的结果会返回在EAX
一般有6个寄存器用来调用系统内核。第一个参数写在 EBX,第二个写进ECX,然后是EDX,ESI, EDI 最后是 EBP。
mov eax,1 ; 调用系统内核 exit 功能
mov ebx,0 ; exit 参数为 0
int 80h ; 终止 80h, 就像是对系统说:"Yo, do this"
当然系统内核可供调用的功能是非常之多的,我们可以在 /usr/include/asm/ 这个目录下找到 unistd.h 文件(也可能是unistd32.h 或者unistd64.h)
里面包含你的系统支持的所有内核调用。 或者查看作者编辑的 Linux System Call Table
表格。
3. 第一个汇编程序 HelloWorld
将以上代码保存在新的文件中,并以 hello.asm 命名该文件。
注:对 helloLen: equ $-hello 行的分析:
在NASM中 美元符 $ 代表所在指令行的行首(也就是前一行的行末地址),前行末尾地址减去hello标志的地址就得到了hello所代表字符串的长度
编译 和链接库
a. 编译 程序
$ nasm -f elf hello.asm
会生成一个 hello.o 文件
b. 链接库
$ ld -s -o hello hello.o
生成最终计算机可执行代码
c. 运行程序
$ ./hello
恭喜你,你的第一个汇编处女程序成功运行啦!当然这个只是初步,要想真正了解汇编,接下来就多实践吧。
注 :如果没有nasm编译软件,可以 sudo apt-get install nasm 安装
原文地址: http://www.cin.ufpe.br/~if817/arquivos/asmtut/index.html#intro
感谢作者 Derick Swanepoel (derick@maple.up.ac.za )