汇编语言学习笔记(4)——汇编基本指令集
注:为讲授方便,使用下列符号:
N | 代表立即数 | N8、N16、N32代表8、16、 32位立即数 |
R | 代表寄存器操作数 | R8、R16、R32代 表8、16、32位寄存器操作数 |
M | 代表内存操作数 | M8、M16、M32代 表8、16、32位内存操作数 |
S | 代表段寄存器 |
一、传送类指令
1. 通用传送
- 数据传送
-
- 功能:源→目,源不变,不影响6种标志
- 说明:CS不能做目标,不能向段寄存器写入立即数 ;禁止2个内存单元直接传送 ;源、目属性要一致
- 有效地址传送
-
- 功能:计算内存单元的有效地址(不是其中的操作数)→目标
- LEA BX , BUF;将BUF单元的有效地址→BX
- LEA BX , [SI+5] ;将数据段SI+5变址的那个单元的有效地址→BX
- 注:有效地址就是偏移地址,LEA指令等效于 OFFSET运算符;LEA BX,BUF 等效于 MOV BX,OFFSET BUF
- 功能:计算内存单元的有效地址(不是其中的操作数)→目标
- 交换指令
-
- 功能:完成2个操作数互换
- 说明: 段寄存器、立即数不能参加互换 !;2个内存操作数不能互换,源、目的类型一致
2 . 堆栈操作指令
- 栈顶:栈区的低地址
- 栈底:栈区的高地址
- 堆栈段寄存器SS:存放堆 栈段段基址
- 堆栈指针ESP(SP):存放 栈顶单元的偏移地址
- SS、ESP(SP)初值,由程序 员赋值或DOS系统自动赋值
- 堆栈指针SP的初值决定了堆栈的大小,SP 始终指向堆栈的顶部,即始终指向最后压入堆栈的信息所在的单元 。
- 堆栈指令
- 堆栈指令
-
-
- 说明:非直接寻址的内存操作数,必须用PTR说明属性
- 出栈指令
-
-
-
- 说明: 非直接寻址的内存操作数,必须用PTR说明属性
- 16位寄存器进栈/出栈
- PUSHA ;依次把AX、CX、DX、BX、 SP、BP、SI、DI压栈(共2´8 字节)
- POPA ;从栈顶弹出2*8字节依次放入DI、 SI、BP、SP、BX、DX、CX、 AX
-
二、算数运算
- 加减法
-
- 功能:ADD :源+目→目
- SUB :目–源→目
- ADC :源+目+上条指令执行后的C标→目
- SBB :目–源–上条指令执行后的C标→目
- 注:此四种操作都影响A、C、O、P、S、Z标志
- 说明:源、目操作数的属性(长度)要一致 ;若操作数中有内存操作数时,请注意是 否需要使用PTR运算符。
- 二进制加减法
-
- 功能:I NC:目+1→目;影响A、O、P、S、Z,不影响C标
- I NC:目+1→目;影响A、O、P、S、Z,不影响C标
- I NC:目+1→目;影响A、C、O、P、S、Z
- 说明:对于非直接寻址的内存操作数,要用PTR 明确说明属性
- 功能:I NC:目+1→目;影响A、O、P、S、Z,不影响C标
- 比较指令
-
- 功能:目-源,产生A、C、O、P、S、Z 6个状态标志, 不破坏源、目。该指令一般后跟条件转移指令。
- 说明:★ 源、目操作数不能同为M ★ 操作数中出现内存操作数时,请注意是否需 要使用PTR运算符
- 二进制乘法
-
- ★ MUL默认乘数、被乘数、乘积为无符号二进数
- ★ IMUL默认乘数、被乘数、乘积为有符号二进数
- ★ 高位积为0,则C标、O标=0,否则为1
- ★ 乘数、被乘数等长,乘积为双倍长
-
- 说明:源、目不能同为M
- 功能:源×目→目
-
- 功能:源×立即数→目
- 二进制除法
-
- 功能:
-
- 说明:★ DIV默认除数、被除数、商、余数均为无 符号数;IDIV默认除数、被除数、商、余数 均为有符号数
- ★ 被除数应为除数的双倍长
- ★ 如除数太小,使商超出范围,则引发CPU中断 ,具体处理方法由操作系统决定,若为DOS操作 系统,则显示:Divided overflow 后返回DOS
- BCD码调整指令
- 组合/未组合BCD码数(即压缩/未压缩BCD 码数)
- 组合BCD码:一字节中含有2位BCD码
- 未组合BCD码:一字节中含有1位BCD码(高4位为0)
- 注意:1010~1111不是BCD码
- BCD码数的加减运算
- 指令系统中没有实现BCD码数加法的指令,只能借用ADD、ADC指令。但是ADD、ADC指令默 认操作数是二进数,其运算法则是“逢二进一” , 而BCD码数加法要求按“逢十进一”运算。
- 因此借用ADD、ADC指令进行BCD码数的加 法还必须对结果进行修正,修正后的结果才是 BCD码数的和数。
- 组合/未组合BCD码数(即压缩/未压缩BCD 码数)
-
-
- 事实上,N1和N2可以是任意的BCD码数, 借用ADD、ADC运算后必须具体分析运算结果, 然后根据不同的情况选择加06H修正,或是加 60H修正,或是加66H修正。 因此借用ADD、ADC指令进行BCD码数的加 法还必须对结果进行修正,修正后的结果才是 BCD码数的和数。
- 如果对于每一次BCD码数的加法都要由 程序员来判断结果的话,这太麻烦了,因此 指令系统中设计了一条“组合BCD码数加法 调整指令¾¾DAA”由硬件进行分析,再对 结果进行调整。
- 上例编程时只需要按以下方式设计程序即可
-
-
- 组合BCD码加法调整:DAA
- 功能:默认操作对象为AL,并且根据具体情况对 AL中的高/低4位进行修正。
- 应用:紧跟在以AL为目标寄存器的ADD/ADC之 后,但AL中必须是组合BCD码数之和。
- 组合BCD码加法调整:DAA
三、 转移和调用指令
- 转移类指令分类
- 按照转移条件分:无条件转移和有条件转移
- 按照转移范围分:段内转移和段间转移
- 按照获取转移地址的方法分: 直接转移和间接转移
- 无条件转移
- 功能:无条件转移,执行指定标号处的指令
-
- 说明: ①标号是转移地址标号。 ②SHORT是短转移,其转移范围相对于指令地址 而言在+129~ -126个单元之间。③段内“JMP 标号”,在实模式下,可转移到64K代码 段的任何位置。
- 有条件转移
-
-
按标志位的当前状态转移(设转移地址标号为XYZ)
-
JC XYZ ;当前C标志为1转
JNC XYZ ;当前C标志为0转
JZ XYZ ;当前Z标志为1转
JNZ XYZ ;当前Z标志为0转
JC XYZ ;当前C标志为1转
JNC XYZ ;当前C标志为0转
JZ XYZ ;当前Z标志为1转
JNZ XYZ ;当前Z标志为0转
-
- 无符号数条件转移(设转移地址标号为XYZ)
- 应用:CMP N1, N2 ;N1,N2为无符号数
- 无符号数条件转移(设转移地址标号为XYZ)
JA XYZ ;N1 > N2转 JNA XYZ ;N1≤N2转 JC XYZ ;N1 < N2转 JNC XYZ ;N1 ≥ N2转
-
- 有符号数条件转移(设转移地址标号为XYZ)
- 应用:CMP N1,N2; N1,N2 为有符号数(机器数)
- 有符号数条件转移(设转移地址标号为XYZ)
JG XYZ ;被减数的真值大于减数的真值转
JGE XYZ ;被减数的真值大于等于减数的真值转
JL XYZ ;被减数的真值小于减数的真值转
JLE XYZ ;被减数的真值小于等于减数的真值转
-
- 循环控制转移
LOOP XYZ ;CX-1→ CX, 结果不为零转
-
-
- 注意:循环控制转移,其转移范围相对于指令地址 而言为:-126 ~+129
-
- 调用与返回指令
- ★ 调用:调用子程序,即无条件转到子程序的第一条指令
- ★ 返回:返回断点,即返回到CALL的后继指令
- ★ 子程序:能完成一定功能的相对独立的程序段
-
- 汇编语言的子程序(也称为过程)定义语句
过程名 PROC 属性
子程序实体
RET
过程名 ENDP
-
- 说明:
- 过程名,即子程序名,以字母开头,长度≤31 ! 经汇编之后,过程名就是子程序第一条指令的地址。
- PROC/ENDP 是子程序的定界语句
- 属性 有2种描述:1、NEAR(或缺省)代表近过程,即该子程序和调用它的那条指令在同一个代码段;2、FAR 代表远过程,即该子程序和调用它的那条指令不在同一个代码段
- RET子程序返回指令
- 段内调用
- 说明:
-
-
- 功能: 断口偏移地址→堆栈
- (SP)←(SP)-2 [CS:IP]←(IP)
- 子程序入口的偏移地址→IP,从而转子程序
- 功能: 断口偏移地址→堆栈
- 段间调用
-
-
-
- 功能: 断口的“段基址:偏移地址”→堆栈
- 首先 (SP)←(SP)-2 [ CS:IP ]←(CS)
- 然后 (SP)←(SP)-2 [ CS:IP ]←(IP)
- 子程序入口的“段基址:偏移地址”→CS:IP, 实现段间转移
- 功能: 断口的“段基址:偏移地址”→堆栈
- 段内/段间返回指令 RET
- 功能: 有NEAR属性的RET指令,从栈顶弹出2字节→IP
- (IP)←[CS:IP] (SP)←(SP) + 2
- 有FAR属性的RET指令,从栈顶弹出4字节→IP,CS
- (IP)←[CS:IP] (SP)←(SP) + 2
- (CS)←[CS:IP] (SP)←(SP) + 2
- 如果栈顶是断口地址,则能返回断点,否则不能
-
- 中断调用与中断返回
- 中断调用 INT N (N=0 ~ 255)
- 功能:标志寄存器→ 堆栈
- “ INT N ”的后继指令地址“CS:IP”→堆栈 无条件转向N型中断服务程序
- 中断返回 IRET
- 功能:从栈顶依次弹出6 个元素→ IP,CS,标志寄存器
- 中断调用 INT N (N=0 ~ 255)
四、逻辑运算
说明:移位指令的操作数为R/M, 移位次数可以是立即数或CL
五、串操作指令
- 串(内存串)的定义: 内存中若干连续的变量(字节,字或双字)
- 关于串操作指令的总说明
- 80X86有6条串操作指令,它们是串传送、串比较、串搜索、串装入、串存储和I/O串操作,本小节仅介绍前5条。
- 各种串操作指令虽然功能不同,但有许多共同之处,例如: 源串和目标串的存储及寻址方式都有隐含规定,即:源串要 放在数据段,目标串要放在ES附加段,在16位寻址操作,CPU 自动用SI间址访问数据段,用DI间址访问ES附加段、用CX做 为串计数器。在32位寻址操作下,CPU自动用ESI间址访问数 据段,用EDI间址访问ES附加段,用ECX做串计数器。
- 由于实模式下逻辑段的最大体积为64K,没有必要使用32 位寻址,为了描述方便,在介绍指令功能的时候,均以16位寻址为基础。
- 串传送
- 功能:把DS:[SI]的若干元素→ ES:[DI]的若干单元
-
- 说明: ①关于“元素”的概念 在字节串传送指令中,一个元素就是1个字节 在字串传送指令中,一个元素为2个字节 在双字串传送指令中,一个元素为4个字节
- ②指令执行前的准备工作: 源串的首地址/末地址→DS:SI 目串的首地址/末地址→ES:DI D标志置0/置1
- ③该指令传送一个元素后,CPU自动修改SI,DI 当D标志为0时,SI,DI增量修改 当D标志为1时,SI,DI减量修改
- 说明: ①关于“元素”的概念 在字节串传送指令中,一个元素就是1个字节 在字串传送指令中,一个元素为2个字节 在双字串传送指令中,一个元素为4个字节
-
- 准备工作:① 同基本型格式 ② 欲传送的元素个数→CX
- 串装入
-
- 准备工作:串首址/末址→DS:SI,0/1 →D标
- 串存储
-
- 准备工作:目标区首址/末址→ES:DI,0/1 →D标
-
- 准备工作:同基本型;欲存储的元素个数→CX
- 功能:每存储一个元素,自动修改DI, 且CX-1→CX, CX=0时止
- 串比较
- 比较两串字符是否相等。两串字符对应字符相等,则两串字符相等,有一个字符不等,则两串字符不等
-
- 准备工作:源串首址/末址→DS:SI;目串首址/末址→ES:DI ,0/1 →D标
-
- 准备工作:同基本型;串元素的个数→ CX
-
- Z标志在具有REPE/REPNE的串指令中的实际使用: 通过Z的取值(Z=0或Z=1)可以判断重复进行 的串指令是否正常退出,以便进行下一步处理。
- 串搜索
- 在ES:[DI]的目标区,搜索是否有规定的“关键字”
-
- 准备:目标区首址/未址→ES:DI, 0/1 →D标;关键字→AL/AX/EAX。
- 功能:比较AL/AX/EAX=ES:[DI]? 修改DI
- 若ES:[改前DI]=关键字,则Z置1,否则Z置0
-
- 准备工作:同基本型;目标串元素的个数→ CX
六、 处理机控制指令
- C标置0 CLC
- C标置1 STC
- C标取反 CMC
- D标置0 CLD
- D标置1 STD
- I标置0 CLI
- I标置1 STI
- 空操作 NOP
- 暂停 HLT