首页
课程
问答
CTF
社区
招聘
峰会
发现
排行榜
知识库
工具下载
看雪20年
看雪商城
证书查询
登录
注册
首页
社区
课程
招聘
发现
问答
CTF
排行榜
知识库
工具下载
峰会
看雪商城
证书查询
社区
茶余饭后
发新帖
0
0
[分享]8086汇编语言基础知识
发表于: 2026-7-22 15:07
1100
[分享]8086汇编语言基础知识
initiate
2026-7-22 15:07
1100
# 8086汇编语言基础知识 > 参考书目:王爽《汇编语言》(第4版) > 处理器架构:Intel 8086 --- ## 一、基础原理 ### 1.1 计算机基本结构 计算机由 CPU(中央处理器)、内存(存储器)和 I/O 设备(外部设备)三大部分组成。CPU 是计算机的核心,负责执行指令;内存用于存储程序和数据;I/O 设备实现人机交互和数据输入输出。 CPU 通过**总线(Bus)** 与内存和 I/O 设备连接。8086 CPU 的外部总线分为三类: | 总线类型 | 宽度 | 作用 | 说明 | |---------|------|------|------| | 地址总线(Address Bus) | 20 根 | 传送地址信息 | 可寻址 2^20 = 1MB 内存空间 | | 数据总线(Data Bus) | 16 根 | 传送数据信息 | 一次可传送 16 位(2 字节)数据 | | 控制总线(Control Bus) | 若干根 | 传送控制信号 | 包括读/写信号、中断请求、中断响应等 | ### 1.2 内存与地址 内存是计算机中用于存储程序和数据的部件。内存被划分为若干个存储单元,每个存储单元可存储 1 字节(8 bit)的数据。每个存储单元都有一个唯一的编号,称为**地址(Address)**。 8086 CPU 有 20 根地址线,因此可寻址的内存空间为 2^20 = 1,048,576 字节 = **1MB**,地址范围为 **00000H ~ FFFFFH**。 关键概念: | 概念 | 说明 | |------|------| | 字节(Byte) | 8 个二进制位(bit),内存的基本存储单位 | | 字(Word) | 16 个二进制位,即 2 字节,8086 的基本字长 | | 双字(Double Word) | 32 个二进制位,即 4 字节 | | 物理地址 | CPU 实际输出到地址总线上的 20 位地址,唯一标识一个内存单元 | | 段地址 | 16 位的段基址,用于在段式内存管理中定位段的起始位置 | | 偏移地址 | 16 位的段内偏移量,表示数据在段内相对于段起始位置的偏移 | ### 1.3 段地址与物理地址的计算 8086 CPU 内部所有寄存器都是 16 位的,只能直接处理 16 位数据,但地址总线是 20 位的,需要 20 位地址。为了解决这个矛盾,8086 采用**段地址 + 偏移地址**的方式来形成 20 位物理地址。 **物理地址计算公式:** ``` 物理地址 = 段地址 × 10H + 偏移地址 ``` 即段地址左移 4 位(乘以 16),再加上偏移地址,得到 20 位物理地址。 **示例:** | 段地址 | 偏移地址 | 计算过程 | 物理地址 | |--------|---------|---------|---------| | 2000H | 0030H | 2000H × 10H + 0030H = 20000H + 0030H | 20030H | | FFFFH | 0000H | FFFFH × 10H + 0000H = FFFF0H + 0000H | FFFF0H | | 1230H | 0089H | 1230H × 10H + 0089H = 12300H + 0089H | 12389H | | 0000H | FFFFH | 0000H × 10H + FFFFH = 00000H + FFFFH | 0FFFFH | **段的特性:** - 段的起始地址必须是 16 的倍数(即段地址 × 10H) - 段的最大长度为 64KB(偏移地址范围 0000H ~ FFFFH) - 一个物理地址可以由多个不同的"段地址:偏移地址"组合表示(例如 12389H 可以是 1230H:0089H,也可以是 1238H:0009H) ### 1.4 内存分段 8086 将 1MB 内存划分为若干个逻辑段,每个段用于存放特定用途的信息。常见的段类型如下: | 段类型 | 用途 | 对应段寄存器 | 说明 | |--------|------|-------------|------| | 代码段(Code Segment) | 存放程序的指令代码 | CS | CPU 从 CS:IP 指向的地址读取指令执行 | | 数据段(Data Segment) | 存放程序使用的数据 | DS | 程序中访问数据时默认使用 DS 作为段地址 | | 栈段(Stack Segment) | 用于栈操作,存放临时数据 | SS | 栈顶地址由 SS:SP 指向 | | 附加段(Extra Segment) | 附加数据段,常用于串操作 | ES | 串操作指令中目的串的段地址 | ### 1.5 指令执行过程 CPU 执行指令的基本过程如下: 1. CPU 从 **CS:IP** 指向的内存单元读取指令(取指) 2. IP 自动增加,指向下一条指令(IP = IP + 指令长度) 3. CPU 对取出的指令进行译码(译码) 4. CPU 执行该指令所规定的操作(执行) 5. 回到第 1 步,继续下一条指令的执行 **关键要点:** - CS(代码段寄存器)和 IP(指令指针寄存器)共同决定 CPU 当前要执行的指令地址 - CPU 加电或复位时,CS = FFFFH,IP = 0000H,物理地址 = FFFF0H,这是 BIOS 程序的入口 - 8086 的指令长度不固定,从 1 字节到 6 字节不等 ### 1.6 栈(Stack) 栈是一种**后进先出(LIFO)** 的数据结构,8086 在硬件层面支持栈操作。栈段由 SS:SP 指定:SS 为栈段段地址,SP 为栈顶偏移地址。 8086 的栈是**向下生长**的,即每入栈一个数据,SP 减小。 | 操作 | 指令 | SP 变化 | 说明 | |------|------|---------|------| | 入栈(Push) | PUSH AX | SP = SP - 2 | 先将 SP 减 2,再将 AX 的内容存入 SS:SP 指向的内存单元 | | 出栈(Pop) | POP AX | SP = SP + 2 | 先将 SS:SP 指向的内存单元的内容取出送入 AX,再将 SP 加 2 | | 入栈(Push) | PUSH BX | SP = SP - 2 | 将 BX 的值压入栈中 | | 出栈(Pop) | POP DS | SP = SP + 2 | 从栈中弹出一个字送入 DS | **注意:** 8086 的栈操作以**字(16 位)**为单位,每次入栈或出栈都是 2 字节。 ### 1.7 BIOS 与 DOS | 概念 | 说明 | |------|------| | BIOS(基本输入输出系统) | 固化在 ROM 中的程序,提供最基本的硬件控制服务,开机后首先运行 | | DOS(磁盘操作系统) | 运行在 BIOS 之上的操作系统,提供文件管理、程序加载等服务 | | 中断(Interrupt) | CPU 暂停当前程序,转去执行中断处理程序,执行完后返回原程序继续执行 | | 中断向量 | 中断处理程序的入口地址,存放在内存 0000:0000 开始的中断向量表中 | | 中断向量表 | 位于内存 0000H:0000H ~ 0000H:03FFH,共 256 个中断向量,每个占 4 字节 | ### 1.8 寻址方式 8086 汇编语言支持多种寻址方式,用于确定操作数的来源: | 寻址方式 | 说明 | 示例 | 操作数位置 | |---------|------|------|-----------| | 立即寻址 | 操作数直接包含在指令中 | MOV AX, 1234H | 指令本身 | | 寄存器寻址 | 操作数在寄存器中 | MOV AX, BX | 寄存器 | | 直接寻址 | 操作数的偏移地址直接给出 | MOV AX, [1234H] | 内存,DS:1234H | | 寄存器间接寻址 | 操作数的偏移地址在寄存器中 | MOV AX, [BX] | 内存,DS:[BX] | | 寄存器相对寻址 | 寄存器内容加位移量 | MOV AX, [BX+08H] | 内存,DS:[BX+08H] | | 基址变址寻址 | 基址寄存器加变址寄存器 | MOV AX, [BX+SI] | 内存,DS:[BX+SI] | | 相对基址变址寻址 | 基址+变址+位移量 | MOV AX, [BX+SI+08H] | 内存,DS:[BX+SI+08H] | **可用于间接寻址的寄存器:** | 寄存器 | 默认段寄存器 | 说明 | |--------|-------------|------| | BX | DS | 基址寄存器 | | BP | SS | 基址指针,默认使用栈段 | | SI | DS | 源变址寄存器 | | DI | DS | 目的变址寄存器 | ### 1.9 数据类型与存储顺序 8086 采用**小端模式(Little-Endian)**:低字节存放在低地址,高字节存放在高地址。 | 数据 | 占用字节 | 内存存储示例(地址从低到高) | |------|---------|---------------------------| | 字节(Byte) 45H | 1 字节 | 45 | | 字(Word) 1234H | 2 字节 | 34 12 | | 双字(DWord) 12345678H | 4 字节 | 78 56 34 12 | --- ## 二、寄存器 ### 2.1 通用寄存器 8086 CPU 有 4 个 16 位通用寄存器,每个都可以拆分为两个独立的 8 位寄存器使用。 | 16位寄存器 | 高8位 | 低8位 | 主要用途 | 特殊用途 | |-----------|-------|-------|---------|---------| | AX(累加器) | AH | AL | 算术运算、逻辑运算的默认操作数 | 乘除法中隐含使用;I/O 指令中用于传送数据 | | BX(基址寄存器) | BH | BL | 存放内存操作数的基址偏移量 | 可用于寄存器间接寻址 [BX] | | CX(计数寄存器) | CH | CL | 通用数据存储 | LOOP 指令和串操作 REP 前缀中用作循环计数器;移位指令中指定移位次数 | | DX(数据寄存器) | DH | DL | 通用数据存储 | 乘法中存放高 16 位结果;除法中存放被除数的高 16 位;间接 I/O 中存放端口地址 | **通用寄存器的拆分:** ``` AX = AH : AL (AH 为高 8 位,AL 为低 8 位) BX = BH : BL CX = CH : CL DX = DH : DL ``` **各寄存器在乘除法中的隐含使用:** | 运算 | 指令 | 隐含使用的寄存器 | 说明 | |------|------|-----------------|------| | 字节乘法 | MUL BL | AX = AL × BL | 被乘数在 AL,结果在 AX | | 字乘法 | MUL BX | DX:AX = AX × BX | 被乘数在 AX,结果高位在 DX,低位在 AX | | 字节除法 | DIV BL | AL = AX / BL,AH = AX % BL | 被除数在 AX,商在 AL,余数在 AH | | 字除法 | DIV BX | AX = DX:AX / BX,DX = DX:AX % BX | 被除数在 DX:AX,商在 AX,余数在 DX | ### 2.2 段寄存器 | 寄存器 | 全称 | 作用 | 默认使用场景 | |--------|------|------|-------------| | CS | 代码段寄存器(Code Segment) | 存放当前执行代码所在段的段地址 | CPU 取指令时使用 CS:IP | | DS | 数据段寄存器(Data Segment) | 存放程序数据所在段的段地址 | 访问数据时默认使用 DS 作为段地址 | | SS | 栈段寄存器(Stack Segment) | 存放栈所在段的段地址 | PUSH/POP 操作使用 SS:SP | | ES | 附加段寄存器(Extra Segment) | 存放附加数据段的段地址 | 串操作中目的串使用 ES:DI | **注意:** 段寄存器不能直接参与算术运算,必须通过通用寄存器中转。例如: ```asm MOV AX, 1000H ; 先将段地址送入 AX MOV DS, AX ; 再通过 AX 转送到 DS ``` ### 2.3 控制寄存器 | 寄存器 | 全称 | 位数 | 作用 | |--------|------|------|------| | IP | 指令指针寄存器(Instruction Pointer) | 16 位 | 存放下一条要执行指令的偏移地址,与 CS 配合形成指令的物理地址 | | FLAGS | 标志寄存器 | 16 位(使用 9 位) | 存放运算结果的状态标志和控制标志 | **IP 的特殊性:** IP 不能被直接读写(没有 MOV IP, AX 这样的指令),只能通过跳转指令(JMP、CALL、RET、LOOP 等)来改变其值。 ### 2.4 标志寄存器(FLAGS)详细定义 FLAGS 寄存器中各标志位的位置(位编号从 0 开始): ``` 位编号: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 标志位: - - - - OF DF IF TF SF ZF - AF - PF - CF ``` #### 2.4.1 状态标志位 | 标志位 | 名称 | 位置 | 为 1 时含义 | 为 0 时含义 | 设置条件 | |--------|------|------|-----------|-----------|---------| | CF | 进位标志(Carry Flag) | 第 0 位 | 无符号运算产生进位/借位 | 无符号运算无进位/借位 | 最高位有进位或借位时置 1 | | PF | 奇偶标志(Parity Flag) | 第 2 位 | 结果低 8 位中 1 的个数为偶数 | 结果低 8 位中 1 的个数为奇数 | 根据结果低 8 位中 1 的个数设置 | | AF | 辅助进位标志(Auxiliary Carry Flag) | 第 4 位 | 低 4 位向高 4 位有进位/借位 | 低 4 位向高 4 位无进位/借位 | 第 3 位向第 4 位有进位或借位时置 1 | | ZF | 零标志(Zero Flag) | 第 6 位 | 运算结果为零 | 运算结果不为零 | 运算结果为全 0 时置 1 | | SF | 符号标志(Sign Flag) | 第 7 位 | 运算结果为负(最高位为 1) | 运算结果为非负(最高位为 0) | 等于结果的最高位 | | OF | 溢出标志(Overflow Flag) | 第 11 位 | 有符号运算产生溢出 | 有符号运算无溢出 | 有符号运算结果超出表示范围时置 1 | #### 2.4.2 控制标志位 | 标志位 | 名称 | 位置 | 为 1 时含义 | 为 0 时含义 | 用途 | |--------|------|------|-----------|-----------|------| | TF | 陷阱标志(Trap Flag) | 第 8 位 | 单步执行模式 | 正常执行模式 | 用于调试,每执行一条指令产生单步中断 | | IF | 中断允许标志(Interrupt Flag) | 第 9 位 | 允许可屏蔽中断 | 禁止可屏蔽中断 | 控制 CPU 是否响应外部可屏蔽中断请求 | | DF | 方向标志(Direction Flag) | 第 10 位 | 串操作地址递减(从高到低) | 串操作地址递增(从低到高) | 控制串操作指令中 SI/DI 的增减方向 | #### 2.4.3 OF 与 CF 的区别 | 对比项 | CF(进位标志) | OF(溢出标志) | |--------|--------------|---------------| | 适用对象 | 无符号数运算 | 有符号数运算 | | 含义 | 最高位是否产生进位/借位 | 有符号数运算结果是否超出表示范围 | | 字节运算溢出范围 | 无符号 0 ~ 255 | 有符号 -128 ~ +127 | | 字运算溢出范围 | 无符号 0 ~ 65535 | 有符号 -32768 ~ +32767 | | 典型使用场景 | 无符号数比较(JA/JB) | 有符号数比较(JG/JL) | ### 2.5 变址寄存器 | 寄存器 | 全称 | 默认段 | 用途 | |--------|------|--------|------| | SI | 源变址寄存器(Source Index) | DS | 串操作中作为源操作数的偏移地址;通用寻址中的变址寄存器 | | DI | 目的变址寄存器(Destination Index) | ES | 串操作中作为目的操作数的偏移地址;通用寻址中的变址寄存器 | | BP | 基址指针寄存器(Base Pointer) | SS | 通常用于访问栈段中的数据;访问函数参数和局部变量 | | SP | 栈指针寄存器(Stack Pointer) | SS | 始终指向栈顶,与 SS 配合确定栈顶物理地址 | ### 2.6 寄存器总览 | 类别 | 寄存器 | 位数 | 可否直接赋值 | |------|--------|------|------------| | 通用寄存器 | AX, BX, CX, DX | 16 位 | 可以(MOV AX, 1234H) | | 通用寄存器(8位) | AH, AL, BH, BL, CH, CL, DH, DL | 8 位 | 可以(MOV AL, 45H) | | 变址/指针寄存器 | SI, DI, BP, SP | 16 位 | 可以(MOV SI, 1000H) | | 段寄存器 | CS, DS, SS, ES | 16 位 | 可以,但须通过通用寄存器中转 | | 控制寄存器 | IP | 16 位 | 不可以,只能通过跳转指令修改 | | 标志寄存器 | FLAGS | 16 位 | 不可以,由运算结果自动设置或通过专用指令修改 | --- ## 三、汇编指令 ### 3.1 数据传送指令 | 指令 | 含义 | 作用 | 格式/用法示例 | 对标志位影响 | |------|------|------|-------------|-------------| | MOV | 传送(Move) | 将源操作数的值复制到目的操作数 | MOV AX, BX(寄存器间传送)<br>MOV AX, 1234H(立即数送寄存器)<br>MOV [BX], AX(寄存器送内存)<br>MOV AX, [BX](内存送寄存器) | 不影响任何标志位 | | PUSH | 入栈(Push) | 将操作数压入栈中 | PUSH AX(将 AX 压栈)<br>PUSH [BX](将内存字数据压栈) | 不影响标志位 | | POP | 出栈(Pop) | 从栈中弹出数据到操作数 | POP AX(弹出栈顶数据到 AX)<br>POP DS(弹出栈顶数据到 DS) | 不影响标志位 | | XCHG | 交换(Exchange) | 交换两个操作数的值 | XCHG AX, BX(交换 AX 和 BX)<br>XCHG AL, [BX](交换 AL 和内存字节) | 不影响标志位 | | LEA | 取有效地址(Load Effective Address) | 将操作数的偏移地址送入寄存器 | LEA AX, [BX+SI+08H](将有效地址送入 AX) | 不影响标志位 | | LDS | 加载 DS 和寄存器 | 从内存中取双字,低字送指定寄存器,高字送 DS | LDS SI, [BX]([BX]低字→SI,[BX+2]高字→DS) | 不影响标志位 | | LES | 加载 ES 和寄存器 | 从内存中取双字,低字送指定寄存器,高字送 ES | LES DI, [BX]([BX]低字→DI,[BX+2]高字→ES) | 不影响标志位 | **MOV 指令的限制规则:** - 不能在两个内存单元之间直接传送(MOV [SI], [DI] 是非法的) - 不能将立即数直接送入段寄存器(MOV DS, 1000H 是非法的) - 不能在两个段寄存器之间直接传送(MOV ES, DS 是非法的) - 源操作数和目的操作数的类型(字节/字)必须一致 ### 3.2 算术运算指令 #### 3.2.1 加法与减法 | 指令 | 含义 | 作用 | 格式/用法示例 | 对标志位影响 | |------|------|------|-------------|-------------| | ADD | 加法(Add) | 将两个操作数相加,结果送目的操作数 | ADD AX, BX(AX = AX + BX)<br>ADD AX, 1234H | 影响 CF、ZF、SF、OF、PF、AF | | ADC | 带进位加法(Add with Carry) | 两个操作数相加再加上 CF | ADC AX, BX(AX = AX + BX + CF) | 影响 CF、ZF、SF、OF、PF、AF | | SUB | 减法(Subtract) | 目的操作数减去源操作数 | SUB AX, BX(AX = AX - BX) | 影响 CF、ZF、SF、OF、PF、AF | | SBB | 带借位减法(Subtract with Borrow) | 目的操作数减去源操作数再减去 CF | SBB AX, BX(AX = AX - BX - CF) | 影响 CF、ZF、SF、OF、PF、AF | | INC | 加 1(Increment) | 操作数加 1 | INC AX(AX = AX + 1)<br>INC CX | 影响 ZF、SF、OF、PF、AF,**不影响 CF** | | DEC | 减 1(Decrement) | 操作数减 1 | DEC AX(AX = AX - 1)<br>DEC BX | 影响 ZF、SF、OF、PF、AF,**不影响 CF** | | NEG | 取补(Negate) | 对操作数取补码(即取相反数) | NEG AX(AX = -AX,等价于 0 - AX) | 影响所有状态标志位 | | CMP | 比较(Compare) | 目的操作数减源操作数,但不保存结果,仅设置标志位 | CMP AX, BX(计算 AX - BX,只设置标志位) | 影响 CF、ZF、SF、OF、PF、AF | #### 3.2.2 乘法 | 指令 | 含义 | 作用 | 格式/用法 | 隐含操作数 | 结果存放 | |------|------|------|---------|-----------|---------| | MUL | 无符号乘法 | 无符号数相乘 | MUL BL | 被乘数:AL | AX = AL × BL | | MUL | 无符号乘法 | 无符号数相乘 | MUL BX | 被乘数:AX | DX:AX = AX × BX | | IMUL | 有符号乘法 | 有符号数相乘 | IMUL BL | 被乘数:AL | AX = AL × BL(有符号) | | IMUL | 有符号乘法 | 有符号数相乘 | IMUL BX | 被乘数:AX | DX:AX = AX × BX(有符号) | **乘法说明:** - 字节乘:AL × 源操作数 → AX(结果 16 位) - 字乘:AX × 源操作数 → DX:AX(结果 32 位,DX 存高 16 位,AX 存低 16 位) - MUL 用于无符号数,IMUL 用于有符号数 - 如果结果的高半部分(AH 或 DX)不为 0,则 CF = OF = 1 #### 3.2.3 除法 | 指令 | 含义 | 作用 | 格式/用法 | 被除数 | 商 | 余数 | |------|------|------|---------|--------|-----|------| | DIV | 无符号除法 | 无符号数相除 | DIV BL | AX(16 位被除数) | AL(8 位商) | AH(8 位余数) | | DIV | 无符号除法 | 无符号数相除 | DIV BX | DX:AX(32 位被除数) | AX(16 位商) | DX(16 位余数) | | IDIV | 有符号除法 | 有符号数相除 | IDIV BL | AX(有符号) | AL | AH | | IDIV | 有符号除法 | 有符号数相除 | IDIV BX | DX:AX(有符号) | AX | DX | **除法说明:** - 字节除:AX / 源操作数 → 商在 AL,余数在 AH - 字除:DX:AX / 源操作数 → 商在 AX,余数在 DX - 如果商超出寄存器能表示的范围,将触发**除法溢出中断(中断 0)** - DIV 用于无符号数,IDIV 用于有符号数 #### 3.2.4 符号扩展指令 | 指令 | 含义 | 作用 | 说明 | |------|------|------|------| | CBW | 字节扩展为字(Convert Byte to Word) | 将 AL 的符号位扩展到 AH | AL 为正数时 AH = 00H;AL 为负数时 AH = FFH | | CWD | 字扩展为双字(Convert Word to Double Word) | 将 AX 的符号位扩展到 DX | AX 为正数时 DX = 0000H;AX 为负数时 DX = FFFFH | ### 3.3 逻辑运算指令 | 指令 | 含义 | 作用 | 格式/用法示例 | 对标志位影响 | |------|------|------|-------------|-------------| | AND | 逻辑与 | 按位进行与运算 | AND AX, 0FF0H(屏蔽 AX 低 4 位)<br>AND AL, 0DFH(将第 5 位清 0) | CF=0,OF=0,影响 ZF、SF、PF | | OR | 逻辑或 | 按位进行或运算 | OR AX, 000FH(将 AX 低 4 位置 1)<br>OR AL, 20H(将第 5 位置 1) | CF=0,OF=0,影响 ZF、SF、PF | | NOT | 逻辑非 | 按位取反 | NOT AX(AX 各位取反) | **不影响任何标志位** | | XOR | 逻辑异或 | 按位进行异或运算 | XOR AX, AX(将 AX 清零)<br>XOR AL, 20H(翻转第 5 位) | CF=0,OF=0,影响 ZF、SF、PF | | TEST | 测试 | 按位进行与运算,但不保存结果,仅设置标志位 | TEST AL, 01H(测试最低位是否为 1) | CF=0,OF=0,影响 ZF、SF、PF | **常用技巧:** | 操作 | 指令 | 说明 | |------|------|------| | 寄存器清零 | XOR AX, AX | 比 MOV AX, 0 更高效(指令更短) | | 屏蔽特定位 | AND AL, 0F0H | 保留高 4 位,低 4 位清零 | | 设置特定位 | OR AL, 01H | 将最低位置 1 | | 翻转特定位 | XOR AL, 0FFH | 将 AL 所有位翻转 | | 测试特定位 | TEST AL, 80H | 测试最高位是否为 1(不改变 AL 的值) | ### 3.4 移位与循环移位指令 #### 3.4.1 移位指令 | 指令 | 含义 | 作用 | 格式/用法 | 对标志位影响 | |------|------|------|---------|-------------| | SHL | 逻辑左移(Shift Left) | 各位左移,低位补 0 | SHL AX, 1(左移 1 位)<br>SHL AX, CL(左移 CL 位) | CF = 最后移出的位,影响 ZF、SF、PF、OF | | SHR | 逻辑右移(Shift Right) | 各位右移,高位补 0 | SHR AX, 1(右移 1 位) | CF = 最后移出的位,影响 ZF、SF、PF、OF | | SAL | 算术左移(Shift Arithmetic Left) | 与 SHL 相同,各位左移,低位补 0 | SAL AX, 1 | 同 SHL | | SAR | 算术右移(Shift Arithmetic Right) | 各位右移,高位补符号位(保持符号不变) | SAR AX, 1(右移 1 位,符号位不变) | CF = 最后移出的位,影响 ZF、SF、PF、OF | **移位指令说明:** - 移位 1 位时直接写 1(如 SHL AX, 1) - 移位多位时必须将移位次数放入 CL 寄存器(如 MOV CL, 4 然后 SHL AX, CL) - SHL 左移 1 位相当于无符号数乘以 2 - SHR 右移 1 位相当于无符号数除以 2 - SAR 右移 1 位相当于有符号数除以 2(保持符号) #### 3.4.2 循环移位指令 | 指令 | 含义 | 作用 | 格式/用法 | 对标志位影响 | |------|------|------|---------|-------------| | ROL | 循环左移(Rotate Left) | 各位左移,最高位移入最低位,同时移入 CF | ROL AX, 1 | CF = 最后移出的位(最高位),OF 在移 1 位时受影响 | | ROR | 循环右移(Rotate Right) | 各位右移,最低位移入最高位,同时移入 CF | ROR AX, 1 | CF = 最后移出的位(最低位),OF 在移 1 位时受影响 | | RCL | 带进位循环左移(Rotate through Carry Left) | 各位左移,CF 移入最低位,最高位移入 CF | RCL AX, 1 | CF = 最后移出的位(最高位) | | RCR | 带进位循环右移(Rotate through Carry Right) | 各位右移,CF 移入最高位,最低位移入 CF | RCR AX, 1 | CF = 最后移出的位(最低位) | ### 3.5 控制转移指令 #### 3.5.1 无条件转移 | 指令 | 含义 | 作用 | 格式/用法 | 说明 | |------|------|------|---------|------| | JMP | 无条件跳转(Jump) | 无条件转移到目标地址执行 | JMP label(段内直接跳转)<br>JMP AX(段内间接跳转)<br>JMP FAR PTR label(段间直接跳转) | 修改 IP(段内)或 CS:IP(段间) | **JMP 的跳转类型:** | 类型 | 格式 | 修改的寄存器 | 说明 | |------|------|-------------|------| | 段内直接跳转 | JMP label | IP | 目标地址在编译时确定 | | 段内间接跳转 | JMP AX / JMP WORD PTR [BX] | IP | 目标地址在寄存器或内存中 | | 段间直接跳转 | JMP FAR PTR label | CS 和 IP | 跳转到另一个代码段 | | 段间间接跳转 | JMP DWORD PTR [BX] | CS 和 IP | 从内存取 32 位地址送入 CS:IP | #### 3.5.2 条件转移指令 条件转移指令根据标志位的状态决定是否跳转,只能进行**段内短转移**(偏移范围 -128 ~ +127)。 **基于单个标志位的条件转移:** | 指令 | 含义 | 转移条件 | 等价指令 | |------|------|---------|---------| | JZ / JE | 为零/相等则跳转(Jump if Zero/Equal) | ZF = 1 | JZ 和 JE 等价 | | JNZ / JNE | 不为零/不相等则跳转(Jump if Not Zero/Not Equal) | ZF = 0 | JNZ 和 JNE 等价 | | JS | 为负则跳转(Jump if Sign) | SF = 1 | — | | JNS | 为正则跳转(Jump if Not Sign) | SF = 0 | — | | JO | 溢出则跳转(Jump if Overflow) | OF = 1 | — | | JNO | 不溢出则跳转(Jump if Not Overflow) | OF = 0 | — | | JP / JPE | 偶校验则跳转(Jump if Parity/Parity Even) | PF = 1 | JP 和 JPE 等价 | | JNP / JPO | 奇校验则跳转(Jump if Not Parity/Parity Odd) | PF = 0 | JNP 和 JPO 等价 | | JC | 有进位则跳转(Jump if Carry) | CF = 1 | JB、JNAE | | JNC | 无进位则跳转(Jump if Not Carry) | CF = 0 | JNB、JAE | **无符号数比较的条件转移(CMP 后使用):** | 指令 | 含义 | 转移条件 | 等价指令 | |------|------|---------|---------| | JA | 高于则跳转(Jump if Above) | CF = 0 且 ZF = 0 | JNBE | | JAE | 高于或等于则跳转(Jump if Above or Equal) | CF = 0 | JNB、JNC | | JB | 低于则跳转(Jump if Below) | CF = 1 | JNAE、JC | | JBE | 低于或等于则跳转(Jump if Below or Equal) | CF = 1 或 ZF = 1 | JNA | **有符号数比较的条件转移(CMP 后使用):** | 指令 | 含义 | 转移条件 | 等价指令 | |------|------|---------|---------| | JG | 大于则跳转(Jump if Greater) | ZF = 0 且 SF = OF | JNLE | | JGE | 大于或等于则跳转(Jump if Greater or Equal) | SF = OF | JNL | | JL | 小于则跳转(Jump if Less) | SF ≠ OF | JNGE | | JLE | 小于或等于则跳转(Jump if Less or Equal) | ZF = 1 或 SF ≠ OF | JNG | **CX 为零条件转移:** | 指令 | 含义 | 转移条件 | |------|------|---------| | JCXZ | CX 为零则跳转(Jump if CX is Zero) | CX = 0 | #### 3.5.3 循环指令 | 指令 | 含义 | 作用 | 格式/用法 | 说明 | |------|------|------|---------|------| | LOOP | 循环(Loop) | CX 减 1,若 CX ≠ 0 则跳转到目标标号 | LOOP label | 隐含使用 CX 作为计数器 | | LOOPE / LOOPZ | 相等/为零时循环 | CX 减 1,若 CX ≠ 0 且 ZF = 1 则跳转 | LOOPE label | 用于在循环中查找不匹配项 | | LOOPNE / LOOPNZ | 不相等/不为零时循环 | CX 减 1,若 CX ≠ 0 且 ZF = 0 则跳转 | LOOPNE label | 用于在循环中查找匹配项 | **LOOP 指令的执行过程:** 1. CX = CX - 1 2. 若 CX ≠ 0,则 IP = IP + 位移量(跳转到标号处) 3. 若 CX = 0,则顺序执行下一条指令 ### 3.6 调用与返回指令 | 指令 | 含义 | 作用 | 格式/用法 | 说明 | |------|------|------|---------|------| | CALL | 调用子程序(Call) | 将返回地址(IP 或 CS:IP)压栈,然后跳转到子程序 | CALL label(段内调用)<br>CALL FAR PTR label(段间调用) | 段内调用压入 IP,段间调用压入 CS 和 IP | | RET | 返回(Return) | 从栈中弹出返回地址,回到调用点 | RET(段内返回)<br>RET n(段内返回并丢弃 n 字节参数) | 段内返回弹出 IP,段间返回弹出 IP 和 CS | | RETF | 远返回(Return Far) | 段间返回 | RETF | 从栈中弹出 IP 和 CS | **CALL 与 RET 的配对使用:** | 调用方式 | 调用动作 | 返回指令 | 返回动作 | |---------|---------|---------|---------| | 段内调用 CALL label | 压入 IP,跳转到目标地址 | RET | 弹出 IP,返回到调用点 | | 段间调用 CALL FAR PTR label | 压入 CS 和 IP,跳转到目标地址 | RETF | 弹出 IP 和 CS,返回到调用点 | ### 3.7 串操作指令 串操作指令用于对内存中的一批数据进行操作。SI 指向源串(默认 DS 段),DI 指向目的串(默认 ES 段)。DF 标志决定地址变化方向:DF=0 时地址递增,DF=1 时地址递减。 | 指令 | 含义 | 作用 | 格式 | 隐含操作数 | 对标志位影响 | |------|------|------|------|-----------|-------------| | MOVSB | 传送字节串(Move String Byte) | 将 DS:[SI] 的字节传送到 ES:[DI],SI 和 DI 加/减 1 | MOVSB | DS:SI → ES:DI | 不影响 | | MOVSW | 传送字串(Move String Word) | 将 DS:[SI] 的字传送到 ES:[DI],SI 和 DI 加/减 2 | MOVSW | DS:SI → ES:DI | 不影响 | | STOSB | 存字节串(Store String Byte) | 将 AL 的内容存入 ES:[DI],DI 加/减 1 | STOSB | AL → ES:DI | 不影响 | | STOSW | 存字串(Store String Word) | 将 AX 的内容存入 ES:[DI],DI 加/减 2 | STOSW | AX → ES:DI | 不影响 | | LODSB | 取字节串(Load String Byte) | 将 DS:[SI] 的字节送入 AL,SI 加/减 1 | LODSB | DS:SI → AL | 不影响 | | LODSW | 取字串(Load String Word) | 将 DS:[SI] 的字送入 AX,SI 加/减 2 | LODSW | DS:SI → AX | 不影响 | | CMPSB | 比较字节串(Compare String Byte) | 比较 DS:[SI] 和 ES:[DI] 的字节,SI 和 DI 加/减 1 | CMPSB | DS:[SI] - ES:[DI] | 影响 CF、ZF、SF、OF、PF、AF | | CMPSW | 比较字串(Compare String Word) | 比较 DS:[SI] 和 ES:[DI] 的字,SI 和 DI 加/减 2 | CMPSW | DS:[SI] - ES:[DI] | 影响 CF、ZF、SF、OF、PF、AF | | SCASB | 扫描字节串(Scan String Byte) | 比较 AL 和 ES:[DI] 的字节,DI 加/减 1 | SCASB | AL - ES:[DI] | 影响 CF、ZF、SF、OF、PF、AF | | SCASW | 扫描字串(Scan String Word) | 比较 AX 和 ES:[DI] 的字,DI 加/减 2 | SCASW | AX - ES:[DI] | 影响 CF、ZF、SF、OF、PF、AF | **REP 前缀:** | 前缀 | 含义 | 作用 | 搭配指令 | 说明 | |------|------|------|---------|------| | REP | 重复(Repeat) | CX ≠ 0 时重复执行串操作,每次 CX 减 1 | MOVSB/MOVSW、STOSB/STOSW | 用于批量传送或填充 | | REPE / REPZ | 相等时重复 | CX ≠ 0 且 ZF = 1 时重复执行 | CMPSB/CMPSW、SCASB/SCASW | 查找第一个不匹配/不等的元素 | | REPNE / REPNZ | 不相等时重复 | CX ≠ 0 且 ZF = 0 时重复执行 | CMPSB/CMPSW、SCASB/SCASW | 查找第一个匹配/相等的元素 | **方向控制指令:** | 指令 | 含义 | 作用 | 说明 | |------|------|------|------| | CLD | 清方向标志(Clear Direction) | DF = 0,串操作地址递增 | SI/DI 每次加 1 或加 2 | | STD | 置方向标志(Set Direction) | DF = 1,串操作地址递减 | SI/DI 每次减 1 或减 2 | ### 3.8 中断指令 | 指令 | 含义 | 作用 | 格式/用法 | 说明 | |------|------|------|---------|------| | INT | 软中断(Interrupt) | 引发指定类型的中断,调用中断处理程序 | INT 10H(调用 BIOS 视频服务)<br>INT 21H(调用 DOS 系统服务) | 压入 FLAGS、CS、IP,然后跳转到中断处理程序 | | IRET | 中断返回(Interrupt Return) | 从中断处理程序返回 | IRET | 弹出 IP、CS、FLAGS,返回到被中断的程序 | | INTO | 溢出中断(Interrupt on Overflow) | 若 OF = 1 则触发中断 4 | INTO | 常用于除法溢出检测 | **常用 BIOS 中断(INT 10H):** | AH 值 | 功能 | 主要参数 | |--------|------|---------| | 02H | 设置光标位置 | BH = 页号,DH = 行号,DL = 列号 | | 06H | 屏幕窗口上滚 | AL = 滚动行数,BH = 属性,CH/CL = 窗口左上角,DH/DL = 窗口右下角 | | 09H | 在光标处显示字符 | AL = 字符,BH = 页号,BL = 属性,CX = 重复次数 | | 0EH | 以电传方式显示字符 | AL = 字符,BL = 前景色 | **常用 DOS 中断(INT 21H):** | AH 值 | 功能 | 主要参数 | 返回值 | |--------|------|---------|--------| | 01H | 从键盘输入一个字符并回显 | 无 | AL = 输入字符的 ASCII 码 | | 02H | 输出一个字符到屏幕 | DL = 要输出的字符 | 无 | | 09H | 输出字符串 | DS:DX = 字符串首地址(以 $ 结尾) | 无 | | 4CH | 程序终止返回 DOS | AL = 返回码 | 无(程序结束) | ### 3.9 输入/输出指令 | 指令 | 含义 | 作用 | 格式/用法 | 说明 | |------|------|------|---------|------| | IN | 输入(Input) | 从端口读取数据到 AL/AX | IN AL, 60H(从端口 60H 读入一个字节到 AL)<br>IN AX, DX(从 DX 指定的端口读入一个字到 AX) | 端口号 0~255 可直接指定,256~65535 须通过 DX | | OUT | 输出(Output) | 将 AL/AX 的数据写入端口 | OUT 60H, AL(将 AL 的内容写入端口 60H)<br>OUT DX, AX(将 AX 的内容写入 DX 指定的端口) | 端口号 0~255 可直接指定,256~65535 须通过 DX | ### 3.10 标志位操作指令 | 指令 | 含义 | 作用 | 说明 | |------|------|------|------| | CLC | 清进位标志(Clear Carry) | CF = 0 | 在进行多精度运算前清除 CF | | STC | 置进位标志(Set Carry) | CF = 1 | — | | CMC | 进位标志取反(Complement Carry) | CF = NOT CF | — | | CLD | 清方向标志(Clear Direction) | DF = 0 | 串操作前通常执行,确保地址递增 | | STD | 置方向标志(Set Direction) | DF = 1 | 使串操作地址递减 | | CLI | 清中断标志(Clear Interrupt) | IF = 0 | 禁止可屏蔽中断 | | STI | 置中断标志(Set Interrupt) | IF = 1 | 允许可屏蔽中断 | | LAHF | 标志送 AH(Load AH from Flags) | AH = FLAGS 的低 8 位 | 将 SF、ZF、AF、PF、CF 送入 AH | | SAHF | AH 送标志(Store AH into Flags) | FLAGS 的低 8 位 = AH | 将 AH 的内容送入标志寄存器低 8 位 | | PUSHF | 标志入栈(Push Flags) | 将 FLAGS 压入栈中 | — | | POPF | 标志出栈(Pop Flags) | 从栈中弹出 FLAGS | — | ### 3.11 其他常用指令 | 指令 | 含义 | 作用 | 格式/用法 | 说明 | |------|------|------|---------|------| | NOP | 空操作(No Operation) | 不执行任何操作,占用一个时钟周期 | NOP | 用于延时或指令对齐 | | HLT | 停机(Halt) | CPU 停止执行指令,等待中断 | HLT | 使 CPU 进入暂停状态 | | XLAT | 查表转换(Translate) | 用 AL 中的值作为偏移量,从表中取出对应字节送入 AL | XLAT | AL = DS:[BX + AL],常用于字符转换 | | AAA | ASCII 加法调整 | 调整 AL 中的 ASCII 加法结果 | AAA | 用于 BCD/ASCII 加法运算后的调整 | | AAS | ASCII 减法调整 | 调整 AL 中的 ASCII 减法结果 | AAS | 用于 BCD/ASCII 减法运算后的调整 | | DAA | 压缩 BCD 加法调整 | 调整 AL 中的压缩 BCD 加法结果 | DAA | — | | DAS | 压缩 BCD 减法调整 | 调整 AL 中的压缩 BCD 减法结果 | DAS | — | ### 3.12 伪指令 伪指令不是 CPU 指令,而是在汇编时指导汇编器如何处理源代码的指令。 | 伪指令 | 含义 | 作用 | 用法示例 | | -------------- | ------------------------ | -------------------- | ----------------------------- | | DB | 定义字节(Define Byte) | 在内存中分配并初始化字节数据 | DB 1, 2, 3, 'ABC' | | DW | 定义字(Define Word) | 在内存中分配并初始化字数据 | DW 1234H, 5678H | | DD | 定义双字(Define Double Word) | 在内存中分配并初始化双字数据 | DD 12345678H | | DUP | 重复(Duplicate) | 与 DB/DW/DD 配合,批量定义数据 | DB 100 DUP(0)(定义 100 个字节全为 0) | | SEGMENT / ENDS | 段定义 | 定义一个逻辑段的开始和结束 | DATA SEGMENT ... DATA ENDS | | ASSUME | 段假定 | 告诉汇编器段寄存器与段的对应关系 | ASSUME CS:CODE, DS:DATA | | EQU | 等值定义 | 定义一个常量符号 | COUNT EQU 100 | | OFFSET | 取偏移地址 | 获取变量或标号的偏移地址 | MOV BX, OFFSET BUFFER | | SEG | 取段地址 | 获取变量或标号所在段的段地址 | MOV AX, SEG BUFFER | | PTR | 类型指定(Pointer) | 指定操作数的类型 | MOV BYTE PTR [BX], 0FFH | | PROC / ENDP | 过程定义 | 定义一个子过程 | SUB1 PROC ... SUB1 ENDP | | END | 源程序结束 | 标记源程序的结束,可指定程序入口 | END START | --- ## 附录:8086 指令编码参考 ### 操作数大小指定 | 后缀 | 含义 | 对应大小 | 使用场景 | |------|------|---------|---------| | BYTE PTR | 字节操作 | 8 位(1 字节) | MOV BYTE PTR [BX], 0FFH | | WORD PTR | 字操作 | 16 位(2 字节) | MOV WORD PTR [BX], 1234H | | DWORD PTR | 双字操作 | 32 位(4 字节) | MOV DWORD PTR [BX], 12345678H | | FAR PTR | 远转移/调用 | 段间转移 | JMP FAR PTR label | | NEAR PTR | 近转移/调用 | 段内转移 | JMP NEAR PTR label | | SHORT | 短转移 | 段内短转移(-128~+127) | JMP SHORT label |
传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!!
收藏
・
0
点赞
・
0
打赏
分享
分享到微信
分享到QQ
分享到微博
赞赏记录
参与人
雪币
留言
时间
查看更多
赞赏
×
1 雪花
5 雪花
10 雪花
20 雪花
50 雪花
80 雪花
100 雪花
150 雪花
200 雪花
支付方式:
微信支付
赞赏留言:
快捷留言
感谢分享~
精品文章~
原创内容~
精彩转帖~
助人为乐~
感谢分享~
最新回复
(
0
)
游客
登录
|
注册
方可回帖
回帖
表情
雪币赚取及消费
高级回复
返回
initiate
1
发帖
0
回帖
0
RANK
关注
私信
他的文章
[分享]8086汇编语言基础知识
1099
关于我们
联系我们
企业服务
看雪公众号
专注于PC、移动、智能设备安全研究及逆向工程的开发者社区
看原图
赞赏
×
雪币:
+
留言:
快捷留言
为你点赞!
返回
顶部