本文主要是介绍【汇编】#6 80x86指令系统其二(串处理与控制转移与子函数),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 一、串处理指令
- 1. 与 REP 协作的 MOVS / STOS / LODS的指令
- 1.1 重复前缀指令REP
- 1.2 字符串传送指令(Move String Instruction)
- 1.2 存串指令(Store String Instruction)
- 1.3 取字符串指令(Load String Instruction)
- 2. 与 REPE(REPNE)配合工作的CMPS 和 SCAS指令
- 2.1 相等重复前缀指令 REPE/REPZ
- 2.2 串比较指令 CMPS
- 2.3 串搜索指令 SCAS
- 3. 串输入输出指令 INS/OUTS
- 二、转移指令
- 1. 无条件转移指令JMP
- 2. 条件转移指令
- 三、循环指令
- 1. 循环指令 LOOP
- 2. (不)相等/(不)为零循环指令 LOOP(N)E/LOOP(BN)Z
- 四、子程序
- 1. 子程序调用CALL
- 1.1 段内直接调用
- 1.2 段内间接调用
- 1.3 段间直接调用
- 1.4 段间间接调用
- 2. 返回指令RET
一、串处理指令
字符串操作指令的实质是对一片连续存储单元进行处理,这 片存储单元是由隐含指针
DS:SI
或ES:DI
来指定的。
字符串操作指令可对内存单元按字节或字进行处理,并能根据操作对象的字节数使变址寄存器SI(和DI)增减1或2。具体规定如下:(DF控制方向)
- 当DF=0时,变址寄存器SI(和DI)增加1或2;
- 当DF=1时,变址寄存器SI(和DI)减少1或2。
1. 与 REP 协作的 MOVS / STOS / LODS的指令
1.1 重复前缀指令REP
重复前缀指令是重复其后的字符串操作指令,重复的次数由 CX来决定。
其一般格式为:
REP MOVS / STOS / LODS
每一次循环CX=CX-1(不影响有关标志位),并执行其后的字符串操作指令,CX=0时,停止循环。
1.2 字符串传送指令(Move String Instruction)
功能:将以SI为指针的源串中的一个字节(或字)存储单元中 的数据传送至以DI为指针的目的地址中去,并自动修改指针,
使之指向下一个字节(或字)存储单元
即REP MOVS
:将数据段中的整串数据传送到附加段中。
- (DS:[SI])→ES:[DI]。
- 当DF=0时,(SI)和(DI)增量;当DF=1时,(SI)和(DI)减量。
- 指令的格式:
MOVS DST,SRC
(需在操作数中表明数据格式)
MOVSB
(字节)
MOVSW
(字) - 执行 REP MOVS 之前,应先做好:
- 源串首地址(末地址)→ SI
- 目的串首地址(末地址)→ DI
- 串长度 → CX
- 建立方向标志
1.2 存串指令(Store String Instruction)
功能:将AL或AX中的数据送入ES:DI所指的目的串中的字节(或 字)存储单元中。
- 字节操作:(AL)→[DI],字操作:(AX)→[DI]。
- 修改指针DI,使之指向串中的下一个元素。
当DF=0时,(DI)增量)。当DF=1时,(DI)减量。 - 指令的格式:
STOS DST
(需在操作数中表明数据格式)
STOSB
(字节)
STOSW
(字)
1.3 取字符串指令(Load String Instruction)
功能:将SI所指的源串中的一个字节(或字)存储单元中的数据取出来送入**AL(或AX)**中。
- 字节操作:([SI])→AL,字操作:([SI])→AX。
- 修改指针SI,使它指向串中的下一个元素。
当DF=0时,(SI)增量。当DF=1时,(SI)减量。 - 指令的格式:
LODS SR
(需在操作数中表明数据格式)
LODSB
(字节)
LODSW
(字)
2. 与 REPE(REPNE)配合工作的CMPS 和 SCAS指令
2.1 相等重复前缀指令 REPE/REPZ
一般格式为:
REPE/REPZ
CMPS/SCAS
- 判断条件:CX≠0 且 ZF=1;(CX=0或ZF=0则退出)若条件不成立,则结束重复操作,执行程序中的下一条指令;
- 条件成立时,CX=CX-1(不影响有关标志位),并执行其后的字符串操作指令,在该指令执行完后,继续对循环条件进行判断。
存在相反指令REPNE/REPNZ
,条件判断CX与上相同,ZF与上相反
2.2 串比较指令 CMPS
将SI所指的源串中的一个字节(或字)存储单元中的数据与DI所指的目的串中的一个字节(或字)存储单元中的数据相减,并根据相减的结果设置标志,但结果并不保存。
- ([SI])-([DI])
- 修改串指针,使之指向串中的下一个
元素。当DF=0时,(SI)和(DI)增量。当DF=1时,(SI)和(DI)减量。 - 格式:
CMPSB
字节串比较CMPSW
字串比较
2.3 串搜索指令 SCAS
AL(字节)或AX(字)中的内容与DI所指的目的串中的一个字节(或字)存储单元中的数据相减,根据相减结果设置标志位,结果不保存
- 字节操作:(AL)-([DI]);字操作:(AX)-([DI])
- 修改指针使之指向串中的下一个元素。当DF=0时,(DI)增量。当DF=1时,(DI)减量。
- 格式:
SCASB
字节串搜索SCASW
字串搜索
3. 串输入输出指令 INS/OUTS
INS:
将由DX寄存器指定的I/O端口中的字、字节传送到附加段中的目的串中,并根据DF和数据类型来改变目的变址寄存器的方向内容
格式:
INSB
字节串输入: ES:[DI] ←((DX)),
DI←DI±1INSW
字串输入: ES:[DI] ← ((DX)),
DI←DI±2
OUTS:
将由源串中的字、字节传送到在DX寄存器指定的
I/O端口中,并根据DF和数据类型来改变源变址寄存器的
方向内容
格式:
OUTSB
字节串输出: ((DX))←DS:[SI]
SI←SI±1OUTSW
字串输出: ((DX))←DS:[SI]
SI←SI±2
二、转移指令
转移指令分无条件转移指令和有条件转移指令两大类。
- 无条件转移指令包括:JMP、子程序的调用和返回指令、中断的调用和返回指令等。
- 条件转移指令又分三大类:
- 基于无符号数的条件转移指令
- 基于有符号数的条件转移指令
- 基于特殊算术标志位的条件转移指令
1. 无条件转移指令JMP
- 段内直接短转移:
JMP (SHORT) OPR
(IP)← (IP)+ 8位位移量 - 段内直接近转移:
JMP (NEAR PTR) OPR
(IP)← (IP)+ 16位位移量
位移量是紧接着JMP指令后的那条指令的偏移地址,到目标指令的偏移地址的地址位移。向地址增大方向转移时,位移量为正;反之位移量为负。
- 段内间接转移:
JMP (WORD PTR) OPR
(IP)← (EA)
将一个寄存器或主存字单元内容送入IP寄存器,作为新的指令指针,但不修改CS寄存器的内容
- 段间直接远转移:
JMP (FAR PTR) OPR
(IP)← OPR 的段内偏移地址
(CS)← OPR 所在段的段地址
将标号所在段的段地址作为新的CS值,标号在该段内的偏移地址作为新的IP值;程序跳转到新的代码段执行
- 段间间接转移:
JMP (DWORD PTR) OPR
(IP)← (EA)
(CS)← (EA+2)
用一个存储单元表示要跳转的目标地址。这个目标地址存放在主存中连续的字单元中的,低位字送IP寄存器,高位字送CS寄存器
2. 条件转移指令
条件转移指令是一组极其重要的转移指令,它根据标志寄存器中的一个(或多个)标志位来决定是否需要转移,这就为实现多功能程序提供了必要的手段
-
基本格式:
JXX LABEL
条件满足,发生转移:IP←IP+位移量
条件不满足,顺序执行指令- 操作数LABEL是采用短转移,称为相对寻址方式
-
单个条件标志的设置情况转移
-
无符号数的条件转移指令
-
有符号数的条件转移指令
-
测试CX的值为0则转移指令
- 条件转移指令中还有一条较特殊的指令,因为CX寄存器通常在程序中用做计数器,JCXZ指令就可以用来判断计数是否为0
- 格式 :
JCXZ LABEL
CX=0,发生转移:IP←IP+位移量;CX≠0,顺序执行下一指令
三、循环指令
1. 循环指令 LOOP
如果(CX)≠0,转向“标号”所指向的指令,否则,终止循环,执行该指令下面的指令。
语句格式: LOOP 标号
使用LOOP指令可代替两条指令:
DEC CX
JNE 标号
转向的范围为-128~+127字节
2. (不)相等/(不)为零循环指令 LOOP(N)E/LOOP(BN)Z
- 对于LOOPE/LOOPZ:
- 语句格式:
LOOPE/ LOOPZ 短标号
- 每次循环(CX)=(CX)-1(不改变任何标志位)
如果CX≠0且ZF=1,则程序转到循环
体的第一条指令,否则,程序将执行该循
环指令下面的指令。
- 语句格式:
- 对于LOOP(N)E/LOOP(BN)Z:
- 使用方法相同,判断条件中的ZF条件相反
四、子程序
子程序是完成特定功能的一段程序。如果某程序段在源程序内反复出现,就可把该程序段定义为子程序。这样可以缩短源程序长度、节省目标程序的存储空间,也可提高程序的可维护性和共享性。
1. 子程序调用CALL
类似但不同于JMP指令,CALL指令需要保存返回地址(调用函数时将下一指令的地址压栈)
- 段内调用——入栈偏移地址IP:
SP←SP-2,SS:SP←IP - 段间调用——入栈偏移地址IP和段地址CS:
SP←SP-2,SS:SP←IP;
SP←SP-2,SS:SP←CS。
1.1 段内直接调用
- 格式:
CALL DST
- 实际步骤:
- 将子程序的返回地址存入堆栈,以便子程序返回使用。即: (SP)←SP - 2;(SP)+1,(SP)←IP
- 转移到子程序入口地址去继续执行子程序。指令中的DST在汇编格式指令作为子程序入口地址的符号地址(标号)。在8086机器语言中,它是一个16位的偏移量。即: (IP)←IP+ D16
1.2 段内间接调用
- 格式:
CALL DST
- 主要区别是子程序的入口地址DST的寻址方式不同而已。它可以是寄存器操作数和各种寻址方式的存储器操作数,当然不允许是立即数和段寄存器操作数。
- 例如:
CALL BX
;BX的内容是子程序的偏移量
CALL word ptr [BX]
;BX所指内存字单元的值是子程序的偏移量
- 例如:
1.3 段间直接调用
- 格式:CALL DST
- 执行操作:
- SP←SP - 2;
- (SP)+1,(SP)←CS ;
- SP←SP - 2;
- (SP)+1,(SP)←IP ;
- IP ←偏移地址(指令的第2、3字节);
- CS ←段地址(指令的第4、5字节);
1.4 段间间接调用
- 格式:CALL DST
- 执行操作:
- SP←SP - 2;
- (SP)+1,(SP)←CS ;
- SP←SP - 2;
- (SP)+1,(SP)←IP ;
- IP ←(EA);
- CS ←(EA+2);
- 主要区别是子程序的入口地址DST的寻址方式不同而已。它可以是寄存器操作数和各种寻址方式的存储器操作数,也即由各种寻址方式形成的有效地址EA和EA+1两个单元内容送入IP,EA+2和EA+3两个单元内容送入CS。
- 例如:
CALL DWORD PTR [BX]
;BX所指内存双字单元的值是子程序的偏移量和段值
- 例如:
2. 返回指令RET
- 段内近返回:RET
实际操作: (IP )← (SP)+1,(SP)
(SP)← SP + 2 - 段内带立即数近返回:RET EXP
RET 可以带有一个立即数 , 堆栈指针 SP 将增加 , 即
SP←SP+EXP。这个特点使得程序可以方便地废除若干执行CALL指令以前入栈参数。 - 段间远返回:RET
实际操作:(IP) ← (SP)+1,(SP)
(SP)←(SP) + 2
(CS)← (SP)+1,(SP)
(SP)←(SP) + 2 - 段间带立即数远返回:RET EXP(同段内带立即数返回)
这篇关于【汇编】#6 80x86指令系统其二(串处理与控制转移与子函数)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!