汇编 ¶
约 1574 个字 19 行代码 预计阅读时间 6 分钟
基本概念¶
助记符、符号、数字等指令
后缀.asm
-> .hex
Intel 语法(例如,用于 x86 架构)¶
- 单行注释:使用分号(
;
)开始注释,直到行尾。例如:
assemblyCopy code
MOV AX, BX ; 这是一个注释
AT&T 语法(GNU 汇编器等)¶
- 单行注释:同样使用分号(
;
)或井号(#
)开始注释,直到行尾。例如:
assemblyCopy code# 这是一个注释
mov %bx, %ax ; 另一个注释
ARM 汇编 ¶
- 单行注释:使用
@
符号开始注释,直到行尾。例如:
assemblyCopy code
MOV R0, R1 @ 这是一个注释
寻址方式 ¶
A 是累加器
立即数寻址 ¶
MOV A,#10H; (A) = 10H
MOV A,#0FFH
直接找到这个人
直接寻址 ¶
MOV A,30H; (A) = 1234
找到房间
寄存器寻址 ¶
MOV A,R0; (A) = (R0)
间接寻址(二级指针)
MOV A,@R0; (A) = ((R0)) = (65H) = 47H
相对寻址
变址寻址
基地址 + 变化指令
位寻址
指令集¶
MAIN: ORG 0030H;
LOOP1: MOV A,#00H;
分号代码注释
传送指令 ¶
通用数据传送指令 ¶
- MOV: 用于将数据从一个地方传送到另一个地方。
- 示例:
MOV AX, BX
// 把BX
寄存器的内容传送到AX
寄存器。
条件传送指令 ¶
CMOVcc
: 根据条件码(cc)来进行条件传送,只有当指定的条件满足时,才执行传送。- 示例:
CMOVE AX, BX
// 如果等于(E)条件满足,则把BX
的值传送到AX
。
堆栈操作指令 ¶
- PUSH: 将数据压入堆栈。
- 示例:
PUSH AX
// 将AX
寄存器的内容压入堆栈。 - PUSHA/PUSHAD: 将所有通用寄存器压入堆栈(PUSHA 是 16 位,PUSHAD 是 32 位
) 。 - 示例:
PUSHAD
// 将所有 32 位通用寄存器压入堆栈。 - POP: 从堆栈中弹出数据。
- 示例:
POP AX
// 将堆栈顶部的内容弹出到AX
寄存器。 - POPA/POPAD: 从堆栈弹出数据到所有通用寄存器(POPA 是 16 位,POPAD 是 32 位
) 。 - 示例:
POPAD
// 从堆栈弹出数据到所有 32 位通用寄存器。
交换指令 ¶
- XCHG: 交换两个操作数的内容。
- 示例:
XCHG AX, BX
// 交换AX
和BX
寄存器的内容。 - XLAT: 根据表(通常在内存中)将一个字节翻译成另一个字节。
- 示例:
XLAT
// 基于BX
寄存器和AL
寄存器的值作为偏移,从表中查找并将结果放入AL
。 - BSWAP: 交换寄存器内字节的顺序(仅限 32 位或更大的寄存器
) 。 - 示例:
BSWAP EAX
// 将EAX
寄存器内的字节顺序反转。
地址或段描述符选择子传送指令 ¶
- LEA (Load Effective Address): 计算有效地址但不实际访问内存,并将结果存储在寄存器中。
- 示例:
LEA AX, [BX+SI]
// 计算BX+SI
的地址并将其存入AX
寄存器。 - LDS, LES, LFS, LGS, LSS: 将特定段的段地址和偏移地址加载到寄存器对中。
- 示例:
LDS SI, [DI]
// 加载DS:SI
寄存器对,其中DS
是段寄存器,SI
是源索引寄存器,地址来自[DI]
。
逻辑运算 ¶
一元运算¶
- INC: 将操作数增加一。
-
示例:
INC AX
//AX = AX + 1
-
DEC: 将操作数减少一。
- 示例:
DEC AX
//AX = AX - 1
二元运算¶
加法运算
- ADD: 对两个操作数进行加法操作。
- 示例:
ADD AX, BX
//AX = AX + BX
- ADC: 加法操作,并加上前一次操作的进位。
- 示例:
ADC AX, BX
//AX = AX + BX + Carry Flag
减法运算
- SUB: 对两个操作数进行减法操作。
- 示例:
SUB AX, BX
//AX = AX - BX
- SBB: 减法操作,并减去前一次操作的借位。
- 示例:
SBB AX, BX
//AX = AX - BX - Borrow Flag
乘法指令
- MUL: 无符号乘法。
- 示例:
MUL BX
//AX = AX * BX
( 假设操作数为 16 位 ) - IMUL: 有符号乘法。
- 示例:
IMUL BX
//AX = AX * BX
( 假设操作数为 16 位 )
除法指令
- DIV: 无符号除法。
- 示例:
DIV BX
// 除以BX
,结果在AX
中(假设操作数为 16 位) - IDIV: 有符号除法。
- 示例:
IDIV BX
// 除以BX
,结果在AX
中(假设操作数为 16 位)
比较操作指令
- CMP: 比较两个操作数,但不保存结果,只更新标志寄存器。
- 示例:
CMP AX, BX
// 比较AX
和BX
逻辑运算指令 ¶
- NOT: 对操作数进行逻辑非操作。
- 示例:
NOT AX
//AX = ~AX
- AND: 逻辑与操作。
- 示例:
AND AX, BX
//AX = AX AND BX
- OR: 逻辑或操作。
- 示例:
OR AX, BX
//AX = AX OR BX
- XOR: 逻辑异或操作。
- 示例:
XOR AX, BX
//AX = AX XOR BX
- TEST: 测试操作,逻辑与操作但结果不保存,只更新标志。
- 示例:
TEST AX, BX
// 测试AX AND BX
示例 ¶
移位指令 ¶
逻辑左移指令 SHL
逻辑右移指令 SHR
算术左移指令 SAL
算术右移指令 SAR
循环左移指令 ROL
循环右移指令 ROR
位操作 ¶
这部分指令包括位测试指令 BT
位测试并置位指令 BTS
位测试并复位指令 BTR
位测试并取反指令 BTC
位向前扫描指令 BSF
位向后扫描指令 BSR
控制转移 ¶
这部分包括无条件转移指令 JMP
条件转移指令 JCC/JCXZ
循环指令 LOOP/LOOPE/LOOPNE
过程调用指令 CALL
子过程返回指令 RET
中断指令 INTn、INT3、INTO、IRET
串操作 ¶
串传送指令 MOVS
串比较指令 CMPS
串扫描指令 SCAN
串加载指令 LODS
串保存指令 STOS
这些指令可以有选择地使用 REP/REPE/REPZ/REPNE 和 REPNZ 的前缀以连续操作
输入输出 ¶
端口输入指令 IN/INS
端口输出指令 OUT/OUTS
寄存器¶
在汇编语言编程中,你将直接与处理器的寄存器交互,用于存储指令、数据和地址。
寄存器赋值 ¶
在汇编语言中,可以直接将一个值赋给寄存器。例如,在 x86 汇编中,可以使用MOV
指令将一个立即数(即常量)赋给寄存器:
MOV EAX, 10 ; 将立即数10赋给寄存器EAX
或者将一个寄存器的值赋给另一个寄存器:
MOV EBX, EAX ; 将寄存器EAX的值赋给寄存器EBX
内存赋值 ¶
在汇编语言中,可以通过将值存储到内存地址来赋值。例如,在 x86 汇编中,可以使用MOV
指令将一个立即数存储到内存地址:
MOV DWORD PTR [0x12345678], 10 ; 将立即数10存储到内存地址0x12345678处
或者将一个寄存器的值存储到内存地址:
MOV DWORD PTR [0x12345678], EAX ; 将寄存器EAX的值存储到内存地址0x12345678处
局部变量赋值 ¶
在汇编语言中,局部变量通常使用堆栈来分配空间。可以使用PUSH
指令将值压入堆栈,或者使用SUB
指令来分配局部变量的空间,然后将值存储到相应的堆栈位置。例如:
SUB ESP, 4 ; 在堆栈上分配4字节的空间
MOV DWORD PTR [ESP], 10 ; 将立即数10存储到堆栈顶部的位置
内存管理¶
汇编程序员需要手动管理内存,包括分配、使用和释放内存。