更好的阅读体验,请点击 YinKai’s Blog。
汇编程序可以分为三个部分:
? 数据部分通常用于存储程序中需要初始化的数据。这可以包括常量、变量和其他静态数据。这个部分的数据在程序运行之前被初始化,并且在整个程序的执行过程中保持不变。
? 声明数据部分的语法如下:
section .data
? 未初始化数据部分用于存储程序中未初始化的全局和静态变量。与数据部分不同,bss 部分的变量在程序加载时不会被初始化,而是在运行时由系统初始化为零或空值。这样可以节省可执行文件的大小,因为在文件中只需要记录这些变量的名称和大小,而不需要存储它们的实际值。
? 声明 bss 部分的语法如下:
section .bss
? 文本部分包含程序的实际代码。这是程序的主要执行部分,包括机器指令和指令的地址。在这个部分,汇编程序将源代码翻译成机器可执行的指令,使得计算机能够按照特定的算法执行相应的操作。
? 声明 文本部分的语法如下:
section .text
? 汇编语言中的注释以分号;
开头。注释可以独立一行存在,也可以与指令在同一行。例如:
; This is a line of comments
add eax, ebx ; adds ebx to eax
? 汇编语言程序由三种类型的语句组成:
? 汇编语言语句每行输入一个语句,每个语句都遵循以下格式:
[label] mnemonic [operands] [;comment]
? 方括号中的字段是可选的。
? 基本指令由两部分组成,第一部分是哟啊执行的指令名词(或助记符),第二部分是命令的操作数或参数。
? 以下是一些典型汇编语言语句的示例:
MOV指令(数据传送):
MOV AX, 42 ; 将值42存储到寄存器AX中
MOV BX, AX ; 将寄存器AX的值传送到寄存器BX中
ADD和SUB指令(加法和减法):
ADD AX, BX ; 将寄存器AX和BX中的值相加,并将结果存储在AX中
SUB CX, 10 ; 从寄存器CX中减去值10,并将结果存储在CX中
CMP和JMP指令(比较和跳转):
CMP AX, BX ; 比较寄存器AX和BX的值
JE label ; 如果相等,则跳转到标签label处
JG another_label ; 如果大于,则跳转到另一个标签another_label处
JL target_label ; 如果小于,跳转到目标标签
INC和DEC指令(递增和递减):
INC SI ; 将寄存器SI中的值递增1
DEC CX ; 将寄存器CX中的值递减1
LOOP指令(循环):
MOV CX, 5 ; 设置循环计数器CX的初始值为5
loop_start: ; 循环开始标签
; 循环体代码
DEC CX ; 循环计数器递减1
JNZ loop_start; 如果计数器不为零,则跳转到循环开始标签
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 -f elf hello.asm
编译汇编程序
-f elf:
这是 NASM 的一个选项,用于指定生成的目标文件的格式。在这里,elf
表示目标文件将采用 ELF(Executable and Linkable Format)格式。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
执行程序