文章根据北京理工大学李元章等老师所著《汇编语言与技术接口》所写,文章仅作为学习笔记使用,不得进行任何商业用途。转载请说明出处!!
这篇文章讲解了汇编中常见的寄存器、CPU工作模式、内存管理。建议读本片文章之前,先花一点时间去阅读 “微处理器管理模式(上)”这篇文章,不然本篇文章出现得一些寄存器可能看不懂。下面是链接~
微处理器管理模式(上)
MOV 目标,源 ;把源操作数传给目标
参与运算的操作数来自CPU内部,包括以下两种寻址方式:
(1)立即寻址方式
操作数直接包含在指令中,紧跟在操作码之后的寻址方式称为立即寻址方式,把该操作数称为立即数,也成为立即数寻址方式。
MOV BL,9 ;执行结果(BL)= 9
9是立即数,它的寻址方式是立即寻址方式。这种寻址方式只能出现在源操作数的位置。除立即寻址外,以下介绍的寻址方式既可以出现在源操作数也可以出现在目标操作数位置。
(2)寄存器寻址方式
操作数直接包含在寄存器中,由指令指定寄存器的寻址方式
寄存器可以是通用寄存器,包括8位、16位、32位通用寄存器;也可以是段寄存器,但是目标寄存器不能是CS。
MOV BX,AX
MOV ECX,9AH
其中,ECX、BX、AX均为寄存器寻址方式,9AH为立即寻址方式。
这两种方式在指令执行时,操作数都存储于CPU中。除以上两种寻址方式外,下一节将介绍的寻址方式的操作数都存储于存储器中。
(1)直接寻址方式
MOV EAX,[00404011H]
[00404011H]是直接寻址方式的一种形式,这里的00404011H用[ ]括起来,它表示一个普通变量的有效地址,而不是操作数本身。
MOV EAX,VAR
由于汇编中用符号表示地址,所以指令中的源操作数VAR的寻址方式是直接寻址方式。若VAR对应的偏移量是00404011H。执行指令“MOV EAX,VAR”时,CPU从指令中知道VAR的地址为00404011H,再从00404011H中取出一个双字,送到EAX。这里VAR是一个内存操作数,它的地址是直接从指令码中取出的,而不必经过极端或其他操作。
段超越前缀格式为:MOV EBX,ES:MEM
指令明确表示使用ES所指向的附加数据段中的变量,而不是默认的DS所指向的数据段。
(2)寄存器间接寻址方式
若指令中使用的是BX、SI、EAX、ECX等,则默认操作数在DS段;若使用的是BP、EBP、ESP,则默认操作数在SS段。
操作数的有效地址在寄存器而操作数本身在存储器中的寻址方式称为寄存器间接寻址。
MOV AL,[BX]
地址计算公式:物理地址=段基址*10H+有效地址
[BX]的寻址方式为寄存器间接寻址方式,注意,BX用[ ]括起来,他表示BX寄存器中是有效地址而不是操作数,这也是寄存器间接寻址与寄存器寻址方式在汇编格式的区别。
(3)寄存器相对寻址
有效地址EA =(基址<或变址>寄存器)+disp
MOV AL,8[BX] ;也可以表示为:MOV AL,[BX+8],8是位移量
实模式下,若(DS)=3000H,(BX)=70H ,(30078H)=12H,则物理地址=10H*(DS)+(BX)+8=30078H,该指令的执行结果是(AL)=12H
(4)基址变址寻址方式
有效地址EA=(基址寄存器)+(编址寄存器)
MOV AL,[BX][SI] / MOV AL,[BX+SI]
MOV EAX,[EBX][ESI]
(5)相对基址变址寻址方式
有效地址EA=(基址寄存器)+(编址寄存器)+disp
MOV AL,ARY[BX][SI] / MOV AL,ARY[BX+SI]
MOV EAX,ARY[EBX][ESI]
(6)比例变址寻址方式
这种寻址方式是80386以上的微处理器才提供的
有效地址EA=(基址寄存器)+(编址寄存器)*比例因子+disp
MOV EAX,ARY[EBX][ESI] ;(DS:[ARY+EBX+ESI]->EAX)
MOV EBX,[EBP+ECX*4+10H] ;(SS:[EBP+ECX*4+10H]->EBX)
(1)传送指令 MOV
格式:MOV DST,SRC
功能:SRC(源)→DST(目标)
说明:MOV指令可以实现一个字节、一个字 、一个双字的数据传送,
注意:源操作数和目标操作数的数据类型匹配问题,即应同为字节、字或双字型数据,可用PTR进行强制转换。
数据传送规则:
– 立即数不能作为目标操作数;
– 立即数不能直接送段寄存器;
– 目标寄存器不能是CS;
– 两个段寄存器间不能直接传送;
– 两个存储单元之间不能直接传送。
MOV AL,5
MOV DS,AX
MOV [BX],AX
MOV ES:VAR,12
MOV WORD PTR [BX],10
MOV EAX,EBX
“WORD PTR” 它明确指出BX所指向的内存 单元为字型,立即数10被汇编为16位的二进制数。若要生成8位的二进制数,需要用 “BYTE PTR”,这里的类型显式说明是必须的。
这里简要概述以下汇编中的PTR的常见用处,下面的文章将不在做说明:
ptr ->pointer (即指针)的缩写。汇编里面 ptr 是规定的字(即保留字),是用来临时指定类型的。
(可以理解为,ptr是临时的类型转换,相当于C语言中的强制类型转换)
mov ax,bx ;是把bx寄存器里的值赋予ax,由于二者都是word型,所以没有必要加“WORD”。
mov ax,word ptr [bx] ;是把内存地址等于“bx寄存器的值”的地方所存放的数据,赋予ax。
由于只是给出一个内存地址,不知道希望赋予ax的是byte还是word,所以需要用word明确指出!
所以,当两个操作数的宽度不一样时,就要用到ptr。
也就是说,*p 用汇编表示就是:dword ptr [p],*p是取p所指内存地址处的值。
总结,即有寄存器时一般不用ptr;没有时一定要用(防止两个操作数的宽度不一样)。
不管用在什么位置,ptr的作用就是临时指定类型。可以放在ptr前面的类型有:
byte(字节)、word(字)、dword(双字)、qword(四字)、tbyte(十字节)、far(远类型)和near(近类型)
(2)带符号扩展的数据传送指令 MOVSX( 386以上)
格式:MOVSX DST,SRC
功能:SRC—>DST,DST空出位用SRC的符号位填充
说明:DST必须是16位或32位寄存器操作数,SRC可以是8位或16位寄存器或存储器操作数,但不能是立即数。
(3)带零扩展的数据传送指令 MOVZX (386以上)
格式:MOVZX DST,SRC
功能:SRC—>DST,DST空出位用0填充
说明:DST必须是16位或32位寄存器操作数,SRC可以是8位或16位寄存器或存储器操作数,但不能是立即数。
(4)交换指令 XCHG
格式:XCHG OPR1,OPR2
功能:交换两个操作数。
说明:OPR是操作数,操作数可以是8位、 16位、32位。两个操作数均不能是立即数,可以是寄存器操作数和存储器操作数,并且其中之一必须是寄存器操作数。
堆栈数据的存取原则是“LIFO”——后进先出
堆栈段段基址→SS
堆栈栈顶地址→SP/ESP
堆栈用途: 对现场数据的保护与恢复、子程序与中断服务返回地址的保护与恢复等。
(1)进栈指令 PUSH
格式:PUSH SRC
功能: SP = SP - 2
SS:SP = (SRC)
说明:SRC可以是16位或32位(386以上) 的寄存器操作数或存储器操作数。在80286以 上的机器中,SRC还可以是立即数。若SRC是 16位操作数,则堆栈指针减2;若SRC是32位 操作数,则堆栈指针减4。
(2)出栈指令 POP
格式:POP DST
功能: (DST) = SS:SP
SP = SP + 2
说明:DST可以是16位或32位(386以 上)的寄存器操作数和存储器操作数,也可 以是除CS寄存器以外的任何段寄存器。若 DST是16位,则堆栈指针加2;若DST是32位 ,则堆栈指针加4。
(1)输入指令 IN
格式: IN ACR,PORT
功能:把外设端口(PORT)的内容传送给累加器(ACR)。
说明:可以传送8位、16位、32位,相应的累加器选择AL、AX、EAX。
(2)输出指令 OUT
格式:OUT PORT,ACR
功能:把累加器的内容传送给外设端口。
说明:对累加器和端口号的选择限制,同IN指令。
MOV AL,0
OUT 61H,AL ;61H端口← (AL) ;关掉PC扬声器
MOV DX,3F8H
OUT DX,AL ;3F8H端口 ← (AL) ;向COM1端口输出一个字符
这类指令传送的是操作数的地址,而不是操作数本身。
(1)传送有效地址指令 LEA
格式:LEA REG,SRC
功能:把源操作数的有效地址送给指定的寄存器。
说明:源操作数必须是存储器操作数。
LEA BX,ASC[SI] ;把DS:[ASC+SI]单元的16位偏移量送给BX
(2)MOV 指令传送地址
MOV 指令除了可以实现数据传送外, 还可实现地址传送,方法是借助于SEG 和OFFSET操作符。
设TAB为一条语句的符号地址,则可以有 以下指令:
MOV AX,SEG TAB ;把TAB的段基址送给AX寄存器
MOV DI,OFFSET TAB ;把TAB的偏移量送给DI寄存器
(1)16位标志进栈指令 PUSHF
格式:PUSHF
功能: 先使堆栈指针寄存器SP-2,然后压入标志寄存器FLAGS的内容到栈顶单元。
SP-2; FLAGS→栈顶单元。
(2)16位标志出栈指令 POPF
格式:POPF
功能:先将堆栈指针所指向的字弹出到FLAGS寄存器,然后使堆栈指针寄存器SP+2
(3)32位标志进栈指令 PUSHFD
格式:PUSHFD
功能:ESP减4;EFLAGS→栈顶。
(4)32位标志出栈指令 POPFD
格式:POPFD
这类指令实际上是把操作数的最高位进行扩展,用于处理带符号数运算的操作数类型匹配问题。这类指令均不影响标志。
所谓符号扩展,就是将数据的表示大小加倍,数值仍保持不变,即将符号位扩展到同样大小的寄存器空间中去,由两部分构成一个比原值表示大一倍的数。
(1)字节扩展成字指令 CBW
格式:CBW
功能:把AL寄存器中的符号位值扩展到AH中
说明:在8086中CBW指令将AL的最高有效位D7扩展至AH,即:如果AL的最高有效位是0,则AH = 00;AL的最高有效位为1,则AH = FFH。AL不变。
例1:AL=88H,执行CBW,AH=FFH
1000 1000
1111 1111 1000 1000
例2:AL=44H,执行CBW,AH=00H
0100 0100
0000 0000 0100 0100
(2)字扩展成双字指令 CWD
格式: CWD
功能:把AX的符号位值扩展到DX中
说明:规则:若AX最高位=1,则执行后DX=FFFFH;若AX最高位=0,则执行后DX=0000H。AX值不变。
(3).双字扩展成四字指令 CDQ
格式:CDQ (386以上)
功能: EAX符号位扩展到EDX中
(4).AX符号位扩展到EAX指令 CWDE
格式: CWDE (386以上)
功能: AX寄存器符号位扩展到EAX高16位
任何一条二进制加、减法指令均适用 于带符号数和无符号数运算。
(1)加法指令 ADD
格式: ADD DST,SRC
功能:(DST)+(SRC)→ DST
说明:对操作数的限定同MOV指令。
标志:影响OF、SF、ZF、AF、PF、CF标志
(2)带进位加法指令 ADC
格式: ADC DST,SRC
功能:(DST)+(SRC)+ CF → DST
说明: 对操作数的限定同MOV指令,该指令 、适用于多字节或多字的加法运算。
标志: 影响OF、SF、ZF、AF、PF、CF标志
ADC AX,35 ;(AX)= (AX)+35+CF
(3)加1指令 INC
格式:INC DST
功能:(DST)+1→DST
标志:除不影响CF标志外,影响其它五个算术运算特征标志。
说明:INC指令的操作数的类型可以是通用寄存器或存储单元,但不可以是段寄存器。字或字节操作均可。对于存储单元,需要用BYTE PTR或者WORD PTR说明是字节还是字操作。
.data
szMsg sbyte 'M1=%d',0ah,0 ;0dh回车,0ah 换行
M1 DW 20
.code
main proc
inc WORD PTR M1
invoke printf,offset szMsg,M1
;下面三行和上边的打印效果相同
mov ax,M1
inc ax
invoke printf,offset szMsg,ax
ret
(4)互换并加法指令 XADD(486以上)
格式:XADD DST,SRC
功能: (DST)+(SRC)→TEMP
(DST)→SRC TEMP→DST
说明:TEMP是临时变量。该指令执行后,原 DST的内容在SRC中,和在DST中。
标志:影响OF、SF、ZF、AF、PF、CF。
(1)减法指令 SUB
格式: SUB DST,SRC
功能:(DST)-(SRC)→ DST
标志: 影响OF、SF、ZF、AF、PF、CF标志。
实例:SUB AX,35
SUB WORD PTR[BX],56
减法指令执行后若使CF=1,则对无符号数而言发生了溢出。若使OF=1,则对带符号数而言发生了溢出。
(2)带借位减法指令 SBB
格式: SBB DST,SRC
功能: (DST)-(SRC)-CF → DST
说明: 除了操作为减外,其它要求同ADC, 该指令适用于多字节或多字的减法运算。 标志:影响OF、SF、ZF、AF、PF、CF
SBB AX,35 ;(AX)= (AX)-35-CF
(3)减1指令 DEC
格式: DEC DST
功能:(DST)-1→DST
说明:使用本指令可以很方便地实现地址指针或循环次数的减1修改。
标志:除不影响CF标志外,影响其它 五个算术运算特征标志。
(4)比较指令 CMP
格式:CMP DST,SRC
功能:(DST)-(SRC),影响标志位。
说明:这条指令执行相减操作后只根据结果设置标志位,并不改变两个操作数的原值,其它要求同SUB。CMP指令常用于比较两个数的大小。
标志:影响OF、SF、ZF、AF、PF、CF标志
(5)求补指令 NEG
格式: NEG DST
功能:对目标操作数(含符号位)求反加1,并且把结果送回目标。即:实现0-(DST)→DST
说明:利用NEG指令可实现求一个数的相反数。 标志:影响OF、SF、ZF、AF、PF、CF标志。其中对CF和OF的影响如下:
(1)无符号乘法指令 MUL
格式:MUL SRC
功能:实现两个无符号二进制数乘。
说明:该指令只含一个源操作数(不能是立即数), 另一个乘数必须事前放在累加器中。可以实现8位、16 位、32位无符号数乘。例如:若操作数是16位的,则与AX中的内容相乘,乘积放在DX:AX这一对寄存器中。具体操作为:
标志:影响CF、OF、SF、ZF、AF、PF,而只有 CF、OF有意义,其它标志不确定。
对CF和OF的影响是:若乘积的高半部分(例:字节型乘法结果的AH)为0,则对CF和OF清0,否则置 CF和OF为1。
(2)带符号乘法指令 IMUL
功能:实现两个带符号二进制数乘。
格式1:IMUL SRC
说明:这种格式的指令除了是实现两个带符号 数相乘且结果为带符号数外,其它与MUL指令相同。 所有的80X86 CPU都支持这种格式。
标志:影响CF、OF、SF、ZF、AF、PF,而只有CF、OF 有意义,其它标志不确定。
对CF和OF的影响是:若乘 积的高半部分为低半部分的符号扩展,则对CF和OF 清0,否则置CF和OF为1。
格式2:IMUL REG,SRC
(286以上)
说明:REG和SRC的长度必须相同,目标操作数 REG必须是16位或32位通用寄存器,源操作数 SRC可以是寄存器或存储器操作数。
具体操作为: (REG)16×(SRC)16→REG16
格式3:IMUL REG,imm8
(286以上)
格式4:IMUL REG,SRCreg/m ,imm8
(286以上)
(1)无符号除法指令 DIV
格式:DIV SRC
功能:实现两个无符号二进制数除法。
说明:该指令只含一个源操作数,该操作数 作为除数使用,注意它不能是立即数。被除数必须事前放在隐含的寄存器中。可以实现8位、16位、 32位无符号数除。
(2)带符号除法指令 IDIV
格式:IDIV SRC
功能:实现两个带符号二进制数除。
说明:除了是实现两个带符号数相除且商和余数 均为带符号数、余数符号与被除数相同外,其它与 DIV指令相同。 具体操作同无符号数除法。
逻辑运算指令见下表。这些指令的操作数可 以是8位、16位、32位,其寻址方式与MOV指令的限制相同。
AND EAX,0 ;将EAX寄存器清0
XOR AL,20H ;转换AL中字母的大小写
从386开始增加了位测试指令,它们包括BT 、BTS、BTR和BTC。这些指令首先把指定位的值送给CF标志,然后对该位按照指令的要求操作。
格式:
BT DEST,SRC
BTC DEST,SRC
BTR DEST,SRC
BTS DEST,SRC
功能:按照源操作指定的位号,测试目的操作数,当指令执行时,被测试位的状态被复制到进位标志CF。
BT将SRC指定的DEST中一位的数值复制到CF。
BTC将SRC指定的DEST中一位的数值复制到CF,且将DEST中该位取反。
BTR将SRC指定的DEST中一位的数值复制到CF,且将DEST中该位清0。
BTS将SRC指定的DEST中一位的数值复制到CF,且将DEST中该位置1。
目标可以是16位或32位的寄存器或存储器操作数,源可以是8位的立即数、寄存器存储器或存储器操作数,若是后两种情况,其长度一定要和目标长度相同。若源操作数是立即数,则其值不应超过目标操作数长度。
(1)顺向扫描指令 BSF
格式:BSF DST,RSC
功能:从右向左扫描RSC操作数中第一个含1的位,并把扫描到的第一个含1的位号送DST操作数。 若RSC=0,则DST值不确定。
(2)逆向扫描指令 BSR
格式:BSR DST,RSC
这类指令实现对操作数移位,包括 SHL、SAL、SHR和SAR指令。
PS:例如SHR(右移):指令使目的操作数逻辑右移一位,最高位用 0 填充。最低位复制到进位标志位,而进位标志位中原来的数值被丢弃
可以用逻辑移位指令实现无符号数乘除法运算,(只要移出位不含1):
SHL DST,n执行后是原数的2^n倍
SHR DST,n执行后是原数的1/2^n
可以用算术移位指令实现带符号数乘除法运算,只要移位操作不改变符号位: SAL DST,n执行后是原数的2^n倍
SAR DST,n执行后是原数的1/2^n (只要移出位不含1)
这类指令实现循环移位操作,包括ROL 、ROR、RCL、RCR指令。
PS:ROL(循环左移)指令把所有位都向左移。最高位复制到进位标志位和最低位。
RCL(带进位循环左移)指令把每一位都向左移,进位标志位复制到 LSB,而 MSB 复制到进位标志位。(通常,MSB位于二进制数的最左侧,LSB位于二进制数的最右侧)
本节讨论的寻址方式是用来确定转移及调用指令的转向地址。即CPU是如何找到下一条指令的。
无条件转移指令格式:JMP 目标
其中的目标有各种寻址方式。这些寻址方式可以被分为段内转移和段间转移两类。段内转移只影响指令指针IP值;段间转移既要影响IP值,也要影响代码段寄存器CS的值。
PS:下面可能会出现这类格式:
转向的有效地址是当前指令指针寄存器的内容和指令中指定的8位、16位位移量之和,该位移量是一个相对于指令指针的带符号数。
EA就是要转向的本代码段内指令地址的偏移量。它是通过把IP的当前值加上指令中给出的位移量disp得到的,从而使IP指向下一条要执行的指令,实现段内转移。
JMP SHORT LAB
。在于当前16位的IP值相加时,系统自动把8位位移量扩展成16位,扩展方法是高8位全部用位移量的符号位填充;在于当前32位的IP值相加时,则高24位全部用位移量的符号位填充。JMP LAB
JMP NEAR PTR LAB
转向的有效地址在一个寄存器或内存单元中,该寄存器号或内存地址按上节介绍的与操作数有关的寻址方式(立即寻址方式除外)获得。所得到的有效地址送给IP,于是实现转移。指令格式及举例见下表。
PS:
JMP WORD PTR [BX]
说明:式中WORD PTR [BX]表示BX指向一个字型内存单元。
1.这条指令执行时,先按照操作数寻址方式得到存放转移地址的内存单元:
10H ×(DS)+(BX)= 20300H
2.再从该单元中得到转移地址:
EA=(20300H)= 0500H
3.于是,(IP)=EA=0500H,下一次便执行CS:500H处的指令,实现了段内间接转移。
指令中直接给出转向的4字节的偏移量和段基址,只需把它们分别送给IP和CS后即可实现段间转移。指令格式:
JMP FAR PTR LAB
图(a)适用于16位操作数长度,执行时把偏移量送给IP,段基址送给CS。
图(b)适用于32位操作数长度,执行时把偏移量送给EIP,段选择符送给CS。
用一个双字内存变量中的低16位取代IP值,高16位取代CS值,从而实现段间转移。该双字变量的地址可以由除立即寻址和寄存器寻址方式以外的其它与数据有关的寻址方式获得。
JMP DWORD PTR [BX]
设:(DS)= 2000H,(BX)= 0300H
(IP)= 0100H,(20300H)= 0
(20301H)= 05H
(20302H)= 10H
(20303H)= 60H
说明:式中DWORD PTR [BX]表示BX指向一个双字变量。
这条指令执行时,先按照与操作数有关的寻址方式得到存放转移地址的内存单元:
10H×(DS)+(BX)= 20300H
再把该单元中的低字送给IP,高字送给CS,即0500H →IP,6010H→CS,
下一次便执行6010:0500H处的指令,实现了段间间接转移。
这类指令包括无条件转移指令和条件转移指令。
(1)无条件转移指令
格式:JMP DST
功能:无条件转移到DST所指向的地址
(2)条件转移指令
执行这类指令时通过检测由前边指令已设置的标志位确定是否转移,所以它们通常是跟在影响标志的指令之后。这类指令本身并不影响标志。
格式:JCC LABEL
功能:如果条件为真,则转向标号处,否则顺序执行下一条指令。
说明:其中cc为条件,LABEL是要转向的标号。在8086-80286中,该地址应在与当前IP值的-128~+127范围之内,即只能使用与转移地址有关的寻址方式的段内短转移格式,其位移量占用一个字节。
格式: JCXZ LABEL
;适用于16位操作数
JECXZ LABEL
;适用于32位操作数
功能:测试CX(或ECX)寄存器的内容,当CX(或ECX)= 0时则转移,否则顺序执行。
说明:此指令经常用于在循环程序中判断循环计数的情况。
循环指令可以控制程序的循环。它们的特点是:
(1)循环指令 LOOP
格式:LOOP LABEL
功能:(CX)-1→CX,若(CX)≠0,则转向标号处执行循环体,否则顺序执行下一条指令。
说明:若操作数长度为32位,则其中的CX应为ECX。在LOOP指令前,应先把循环计数的初始值送给CX(或ECX)。
(2)相等循环指令 LOOPE/LOOPZ
(3)不等循环指令 LOOPNE/LOOPNZ
格式:CALL DST
功能:调用子程序。执行时先把返回地址压入堆栈,再形成子程序入口地址,最后把控制权交给子程序。
说明:其中DST为子程序名或子程序入口地址,其目标地址的形成与JMP指令有异同。
(1)段内调用
这类调用指令实现同一段内的子程序调用,它只改变IP值,不改变CS值。
执行操作:
段内直接调用:
格式:CALL A
或: CALL NEAR PTR A
功能:调用A子程序。执行时先把返回地址压入堆栈,再使IP=(IP)+disp16,最后把控制权交给子程序。
段内间接调用:
格式:CALL REG/M
功能:调用子程序。执行时先把返回地址压入堆栈,再把指令指定的16位通用寄存器或内存单元的内容送给IP,最后把控制权交给子程序。
(2)段间调用
这类调用指令可以实现段间调用(FAR型调用),执行时即要改变IP值,也要改变CS值。
段间直接调用:
格式:CALL FAR PTR PROCEDURE
功能:调用PROCEDURE子程序。执行时先把返回地址(当前IP值和当前CS值)压入堆栈,再把指令中的偏移量部分送给IP,段基址部分送给CS,最后把控制权交给子程序。
段间间接调用:
格式:CALL M
功能:调用子程序。执行时先把返回地址(当前IP值和当前CS值)压入堆栈,再把M的低字送给IP,高字送给CS,最后把控制权交给子程序。
执行这组指令可以返回到被调用处。有两条返回指令,它们都不影响标志。以下介绍8086/8088的子程序调用指令。
返回指令 RET
格式:RET
功能:按照CALL指令入栈的逆序,从栈顶弹出返回地址(弹出一个字到IP,若子程序是FAR型还需再弹出一个字到CS),然后返回到主程序继续执行。
无论子程序是NEAR型还是FAR型,返回指令的汇编格式总是用RET表示。但经汇编后会产生不同的机器码。在DEBUG中,段间返回指令被反汇编成RETF。
带立即数的返回指令
格式:RET imm16
功能:按照CALL指令入栈的逆序,从栈顶弹出返回地址(弹出一个字到IP,若子程序是FAR型还需再弹出一个字到CS),返回到主程序,并修改栈顶指针SP=(SP)+imm16。
注:其中imm16是16位的立即数,设通过堆栈给子程序传递了n个字型参数,则imm16=2n。
修改堆栈指针是为了废除堆栈中主程序传递给子程序的参数。
中断就是使计算机暂时挂起正在执行的进程而转去处理某种事件,处理完后再恢复执行原进程的过程。
对某事件的处理实际上就是去执行一段例行程序,该程序被称为中断处理例行程序或中断处理子程序,简称为中断子程序。
中断调用指令 INT
在8086/8088中,中断分为内中断(或称软中断)和外中断(或称硬中断),本节只介绍内中断的中断调用指令。
格式:INT n ;n为中断类型号
功能:中断当前正在执行的程序,把当前的FLAGS、CS、IP值依次压入堆栈(保护断点),并从中断向量表的4n处取出n类中断向量。其中(4n)→IP,(4n+2)→CS,转去执行中断处理子程序。
中断返回指令 IRET
格式:IRET
功能:从栈顶弹出三个字分别送入IP、CS、FLAGS寄存器,把控制返回到原断点继续执行。
这组指令可以控制处理机状态以及对某些标志位进行操作。
这组指令可以直接对CF、DF和IF标志位进行操作,它们只影响本指令所涉及的标志。
利用块操作指令可以直接处理两个存储器操作数,方便地处理字符串或数据块(批量处理)。
常用的块操作指令:
注:块操作指令中,指令后面的B、W、D代表操作数的大小,分别代表字节、字、双字的内存操作数。
指令格式
块指令可以显式地带有操作数,也可以使用隐含格式。例如块传送指令MOVS,可以有以下几种格式:
显式:MOVS DST, SRC
隐式:MOVSB ;字节传送
MOVSW ;字传送
MOVSD ;双字传送
经常使用隐含格式。操作数时应先建立地址指针。
操作数
块指令可以处理寄存器操作数和存储器操作数。
若为寄存器操作数则只能放在累加器中;
对于存储器操作数应先建立地址指针:若为源操作数,则必须把源串首地址放入SI寄存器,缺省情况寻址DS所指向的段,允许使用段超越前缀;若为目标操作数,则必须把目标串首地址放入ES:DI寄存器,不允许使用段超越前缀。
地址指针的修改
块指令执行后系统自动修改地址指针SI(ESI)、DI(EDI)。若为字节型操作其修改量为1,若为字型操作其修改量为2,若为双字型操作其修改量为4。
方向标志
方向标志DF决定地址指针的增减方向。
DF=0,则地址指针增量;
DF=1,则地址指针减量。
可以用CLD和STD指令复位和置位DF。
重复前缀
块指令前可以加重复前缀REPE/REPZ、 REP或REPNE/REPNZ,使后跟的串指令重复执行。重复次数应事先初始化在计数器CX中。
(1)重复前缀 REP
若(CX)=0,则结束重复,顺序执行下一条指令。
若(CX)≠0,则执行后跟的串操作指令,然后修改计数器(CX)-1→CX,继续重复上述操作。
若地址长度为32位的,则使用ECX。
(2)相等重复前缀 REPE/REPZ
REPE/REPZ可以用在比较类块操作指令之前,当比较相等且重复次数未到时重复执行后跟的串指令。其执行的操作为:
若(CX)=0(计数到)或ZF=0(不相等),则结束重复,顺序执行下一条指令。否则执行后跟的块操作指令,修改计数器(CX)-1→CX。继续重复上述操作。
若地址长度为32位的,则使用ECX。
(3)不等重复前缀 REPNE/REPNZ
MOVS
显式格式:MOVS DSTm,SRCm
隐含格式:MOVSB MOVSW MOVSD
功能:源→目标,即([SI])→ES:[DI],且自动修改SI、DI指针。主要将DS:SI地址的数据复制到ES:DI地址中。
标志:不影响标志位。
在MOVS操作结束后,(E)SI与(E)DI寄存器会自动的增加或者减少,而依据则是根据EFLAGS寄存器中的DF标志位来判断增加还是减少。
LODS
显式格式:LODS SRCm
隐含格式:LODSB LODSW LODSD
功能:源→累加器,即([SI]) →AL(或AX、EAX),且自动修改SI指针。
说明:若DF=0,则LODSB(或LODSW、LODSD)使SI加1(或2、4);若DF=1,则LODSB(或LODSW、LODSD)使SI减1(或2、4)。若地址长度是32位的,则SI相应为ESI。
标志:不影响标志位。
STOS
显式格式:STOS DSTm
隐含格式:STOSB STOSW STOSD
功能:累加器→目标,即(AL(或AX、EAX)) →ES:[DI],且自动修改DI指针。
说明:若DF=0,则STOSB(或STOSW、STOSD)使DI加1(或2、4);若DF=1,则STOSB(或STOSW、STOSD)使DI减1(或2、4)。若地址长度是32位的,则DI相应为EDI。
标志:不影响标志位。
块输入指令 INS
显式格式:INS DSTm,DX
隐含格式:INSB INSW INSD
块输出指令 OUTS
显式格式:OUTS DX,SRCm
块比较指令 CMPS
显式格式:CMPS DSTm,SRCm
块扫描指令 SCAS
显式格式:SCAS DSTm