基本语法
汇编程序可以分为三个部分:
- 数据部分(data section)
- 未初始化数据部分(bss section)
- 文本部分(text section)
data 部分
数据部分通常用于存储程序中需要初始化的数据。这可以包括常量、变量和其他静态数据。这个部分的数据在程序运行之前被初始化,并且在整个程序的执行过程中保持不变。
声明数据部分的语法如下:
section .data
bss 部分
未初始化数据部分用于存储程序中未初始化的全局和静态变量。与数据部分不同,bss 部分的变量在程序加载时不会被初始化,而是在运行时由系统初始化为零或空值。这样可以节省可执行文件的大小,因为在文件中只需要记录这些变量的名称和大小,而不需要存储它们的实际值。
声明 bss 部分的语法如下:
section .bss
text 部分
声明 文本部分的语法如下:
section .text
注释
汇编语言中的注释以分号;开头。注释可以一行存在,也可以与指令在同一行。例如:
; This is a line of comments
add eax, ebx ; adds ebx to eax
汇编语言语句
汇编语言程序由三种类型的语句组成:
- 可执行指令:告诉处理器要执行的操作,每条指令包括操作码和操作数
- **汇编器指令或伪操作:**用于影响汇编过程的方面,它们不会生成机器语言指令
- **宏:**一种文本替换机制
汇编语言语句的语法
汇编语言语句每行输入一个语句,每个语句都遵循以下格式:
[label] mnemonic [operands] [;comment]
方括号中的字段是可选的。
基本指令由两部分组成,第一部分是哟啊执行的指令名词(或助记符),第二部分是命令的操作数或参数。
以下是一些典型汇编语言语句的示例:
汇编中的 Hello World 程序
section .data
msg db 'Hello, world!', 0xa ; 要打印的字符串,0xa 是换行符
len equ $ - msg ; 字符串的长度
section .text
global _start ; 必须为链接器(ld)声明的全局入口点
_start: ; 告诉链接器入口点
; write message to stdout
mov eax, 4 ; 系统调用号(sys_write)
mov ebx, 1 ; 文件描述符(标准输出)
mov ecx, msg ; 要写入的消息
mov edx, len ; 消息的长度
int 0x80 ; 调用内核
; exit the program
mov eax, 1 ; 系统调用号(sys_exit)
xor ebx, ebx ; 返回码为0
int 0x80 ; 调用内核
上面的代码被编译并执行后,会输出如下内容:
Hello, world!
在 NASM 中编译和链接汇编程序
为了能让上面的程序运行起来,我们需要按下面的步骤编译和链接上述程序:
- 使用文本编译器输入上述代码并将其保存为 hello.asm,后续的操作都在该目录下进行
- 输入
nasm -f elf hello.asm 编译汇编程序
-f elf:这是 NASM 的一个选项,用于指定生成的目标文件的格式。在这里,elf 表示目标文件将采用 ELF(Executable and Linkable Format)格式。- ELF 是一种通用的二进制文件格式,用于可执行文件、目标文件和共享库。
- 如果程序没有问题,就会程序名为 hello.o 的程序目标文件
- 输入
ld -m elf_i386 -s -o hello hello.o 命令,链接目标文件并创建名为 hello 的可执行文件
ld: 这是链接器的命令。链接器的作用是将多个目标文件链接在一起,解析符号引用,生成最终的可执行文件。在执行该命令时,链接器会将系统库和其他必要运行时库链接到目标文件 hello.o 中。我们的代码中由于程序只是在标准输出上打印一条消息,因此系统库中的一些 I/O 相关的函数可能被链接进来,以便程序能够正确地执行。-m elf_i386: 这个选项告诉链接器使用 ELF (Executable and Linkable Format) 文件格式,并且生成 32 位 x86 架构的可执行文件。elf_i386 表示生成的可执行文件是面向 32 位 x86 架构的 ELF 文件。-s: 这个选项用于剥离(strip)可执行文件中的符号表信息。符号表包含了程序中定义的各种符号(如变量、函数名等)的信息。在生产环境中,剥离符号表可以减小可执行文件的大小,但同时也会使得可执行文件不易调试。-o hello: 这个选项指定生成的可执行文件的输出名称为 hello。-o 是指定输出文件的选项,后面跟着输出文件的名称。hello.o: 这是输入的目标文件,它是由 NASM 编译器生成的,包含了汇编代码的机器代码。
- 最后通过
./hello 执行程序