跳转至

汇编

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 // 交换AXBX寄存器的内容。
  • 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 // 比较AXBX

逻辑运算指令

  • 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

示例

\[ Y = \overline{A\oplus\overline{B\cdot C}}\cdot\overline{D+A} \]

移位指令

逻辑左移指令 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存储到堆栈顶部的位置

内存管理

汇编程序员需要手动管理内存,包括分配、使用和释放内存。