常用汇编指令(6)-循环指令 ,程序调用指令
2013-12-04 17:16阅读:
5
循环指令
//循环指令不影响条件码
使用相对寻址方式
(1)LOOP
循环
格式:LOOP
OPR
测试条件:(count
Reg)≠0
(2)LOOPZ/LOOPE
当为零或相等时循环指令
格式:LOOPZ(或LOOPE)
OPR
测试条件:ZF=1且(count
Reg)≠0
(3)LOOPNZ/LOOPNE
当不为零或不相等时循环指令
格式:LOOPNZ(或LOOPNE)
OPR
测试条件:ZF=0且(count
Reg)≠0
其中第二和第三条指令提供了提前结束循环的可能性。
这三条指令执行步骤:①(count
Reg)←(count
Reg)-1
②检查是否满足测试条件,如满足且操作数长度为16位,则(IP)←(IP)+D8的符号扩展;如满足且操作数长度为32位,则(EIP)←(EIP)+D8的符号扩展;
上面OPR必须指定一个表示转向地址的标号(符号地址),而在机器指令里则用8位位移量D8来表示转向地址与当前IP(或EIP)值的差。由于位移量只有8位,所以转向地址必须在该循环指令的下一条指令地址的-128~+127字节范围内。
6
子程序
子程序相当于高级语言中的“过程”,(procedure)。程序中可以由调用程序(或称主程序)调用这些子程序,而在子程序执行完后又返回调用程序继续执行。
1.
CALL 调用指令
//不影响标志位
⑴段内直接近调用
执行操作:当操作长度为16位时,Push(IP)
(IP)←(IP)+D16
或(EIP)←( (EIP)+D16
)AND0000FFFFH
操作数长度为32位时,Push(EIP)
(EIP)←(EIP)+D32
指令中DST给出转向地址(即子程序的入口地址,亦即子程序的第一条指令的地址),D16即为机器指令
中的位移量,它是转向地址和返回地址之间的差值。
⑵段内间接近调用
执行操作:当操作长度为16位时,Push(IP)
(IP)←(EA)
或(EIP)←(EA)AND0000FFFFH
操作数长度为32位时,Push(EIP)
(EIP)←(EA)
指令中的DST可使用寄存器寻址方式或任一种存储器寻址方式,由指定的寄存器或存储单元的内容给出转向地址。当操作长度为16位时,则有效地址EA应为16位;操作数长度为32位时,EA应为32位。
以上两种方式均为近调用,转向地址中只包含其偏移地址部分,段地址是保持不变的。
⑶段间直接远调用
执行操作:当操作长度为16位时,
Push(CS)
Push(IP)
(IP)←DST指定的偏移地址
(CS)←DST指定的段地址
当操作长度为32位时,
Push(CS)
Push(EIP)
(EIP)←DST指定的偏移地址
(CS)←DST指定的段地址
由于调用程序和子程序不在同一段内,因此返回的地址的保存以及转向地址的设置都必须把段地址考虑在内。
⑷段间间接远调用
执行操作:当操作长度为16位时,
Push(CS)
Push(IP)
(IP)←(EA)
(CS)←(EA+2)
当操作长度为32位时,
Push(CS)
Push(EIP)
(EIP)←(EA)
(CS)←(EA+4)
其中EA是由DST的寻址方式确定的有效地址,这里可用任一种存储器寻址方式来取得EA值。
2.RET
返回指令
//不影响标志位
RET指令放在子程序的末尾,它使子程序在功能完成后返回调用程序继续执行,而返回地址是调用程序调用子程序(或称转子)时存放在堆栈中的,因此RET指令的操作是返回地址出栈送IP或EIP寄存器(段内或段间)和CS寄存器(段间)。
(1)段内近返回
格式:RET
执行操作:当操作数长度为16时,(IP)←POP()
386及后继机型:(EIP)←(EIP)AND0000FFFFH
当操作数长度为32位时,(EIP)←POP()
(2)段内带立即数近返回
格式:RET
EXP
执行操作:在执行完与(1)的RET完全相同的操作后,还需要修改堆栈指针:
(SP或ESP)←(SP或ESP)+D16
其中EXP是一个表达式,根据它的值计算出来的常数成为机器指令中的位移量D16。这种指令允许返回地址出栈后修改堆栈的指针,这就便于调用程序在用CALL指令调用子程序以前把子程序所需要的参数入栈,以便子程序运行时使用这些参数。当子程序返回后,这些参数已不在有用,就可以修改指针使其指向参数入栈以前的值。
(3)段间远返回
格式:RET
执行操作:当操作数长度为16时,(IP)←POP()
386及后继机型:(EIP)←(EIP)AND0000FFFFH
(CS)←POP()
当操作数长度为32位时,(EIP)←POP()
(CS)←POP()(32位数出栈、高16位废除)
(4)段间带立即数远返回
格式:RET
EXP
执行操作:在执行完与(3)的RET完全相同的操作后,还需要修改堆栈指针:
(SP或ESP)←(SP或ESP)+D16
这里EXP的含义及使用情况与带立即数返回指令相同。
7
中断
中断分为内部中断和外部中断两类。内部中断包括像除法运算中所遇到需要除以0时
产生的中断,或者程序中为了做某些处理而设置的中断指令等。外部中断则主要用来处理I/O设备与CPU之间的通信。
当CPU响应一次中断时,也要和调用子程序时类似地把(IP)或(EIP)和(CS)保存入栈。除此之外,为了能全面地保存现场信息,以便在中断处理结束时返回现场,还需要把反映现场状态的(FLAGS)或(EFLAGS)保存入栈,然后才能转到中断例行程序去执行。返回同理要恢复(FLAGS)或(EFLAGS)。
中断例行程序入口地址称为中断向量。在80X86中,在实模式下工作时,存储器的最低地址区的1024个字节(地址从00000H到003FFH)为中断向量区,其中存放着256种类型中断例行程序的入口地址(中断向量)。由于每个中断向量占有4个字节单元,所以中断指令中指定的类型号N需要乘以4才能取得所指定类型的中断向量。在保护模式下,中断例行程序的入口通过中断描述符表找到找到中断描述符来取得的。由于每个描述符为8字节长,所以类型号应乘以8才能取得所指定类型的中断描述符。
(1)INT
(interrupt)
中断//不影响除IF、TF和AC以外的标志位
格式:INT
TYPE 或 INT
执行操作:PUSH(FLAGS)
IF←0
TF←0
AC←0
PUSH(CS)
PUSH(IP)
(IP)←(TYPE *
4)
(CS)←(TYPE *
4+2)
其中TYPE为类型号,它可以是常数或表达式,其值必须在0~255范围内,格式中的INT是一个字节的中断指令,它隐含的类型号为3。
(2)INTO(interrupt
if overflow)
如溢出则中断//同上
格式:INTO
执行操作:若OF =
1,则:PUSH(FLAGS)
IF←0
TF←0
AC←0
PUSH(CS)
PUSH(IP)
(IP)←(10H)
(CS)←(12H)
(3)IRET(return
from interrupt)
从中断返回//标志位由堆栈中取出来的值设置
格式:IRET
适用于操作数长度为16位的情况
执行操作:(IP)←POP()
(CS)←POP()
(FLAGS)←POP()
(4)IRETD(return
from interrupt)
从中断返回
//标志位由堆栈中取出来的值设置
格式:IRETD
适用于操作数长度为32位的情况
执行操作:(IP)←POP()
(CS)←POP()
(EFLAGS)←POP()
处理机控制和杂项操作指令
1.
标志处理指令
//只影响本指令指定的标志,而不影响其他标志位
·CLC(clear
carry)
进位位置置零指令
CF←0
·CMC
(complement carry)
进位位求反指令
CF←CF
·STC (set
carry)
进位位置1指令
CF←1
·CLD (clear
direction)
方向标志位置0指令
DF←0
·STD (set
direction)
方向标志位置1指令
DF←1
·CLI (clear
interrupt)
中断标志置0指令
IF←0
·STI (set
interrupt)
中断标志置1指令
IF←1
2.
其它处理机控制与杂项操作指令
//以下指令不影响条件码
(1)NOP(no
operation)
无操作指令
该指令不执行任何操作,其机器码占有一个字节单元,在调试程序时往往用这条指令占有一定的存储单元,以便在正式运行时用其他指令取代。
(2)HLT
(halt)
停机
该指令可使机器暂停工作,使处理机处于停机状态以等待一次外部中断的到来,中断结束后继续执行下面.
(3)WAIT
(wait)
等待
该指令使处理机处于空转状态,它也可以用来等待外部中断发生,但中断结束后仍返回WAIT指令继续等待。
它也可以与ESC指令配合等待协处理机的执行结果。
(4)ESC
(escape)
换码
格式:
ESC
op,reg/mem
这条指令在使用协处理机时,可以指定由协处理器执行的指令。指令的第一个操作数即指定其操作码,第二个操作数即指定其操作数。自486起,浮点协处理器已装入CPU芯片,系统可以直接支持协处理器指令,因此ESC指令已成为未定义指令,如遇到程序中的ESC指令将引起一次异常处理。
(5)LOCK
(lock)
封锁
该指令是一种前缀,它可以与其它指令联合,用来维持总线的锁存信号直到与其联合的指令执行完为止。当CPU与其它协处理机协同工作时,该指令可避免破坏有用信息。
LOCK前缀可与下列指令联用:
BTS,BTR,BTC
mem,reg/imm
XCHG
reg,mem
XCHG
mem,reg
ADD,OR,ADC,SBB,AND,SUB,XOR
mem,reg/imm
NOT,NEG,INC,DEC
mem
CMPXCHG,XADD
(6)BOUND(bound)
界限
格式:BOUND
reg,mem
执行操作:BOUND指令检查给出的数组下标是否在规定的上下界之内。如在上下界之内,则执行下一条指令;如超出了上下界范围,则产生中断5。如发生中断,则中断返回时返回地址仍指向BOUND指令,而不是其下一条指令。
指令中第一个操作数必须用寄存器,用来存放当前数组下标。当操作数长度为16位时,使用16位寄存器;而当操作数长度为32位时,则使用32位寄存器。第二个操作数必须使用存储器方式,该操作数用来存放数组的上下界。当操作数长度为16位时,使用相继的两个16位字存放下界和上界,下界存放在低地址所指定的字单元中,上界存放在高地址所指定的字单元中。当操作数为32位时,使用相继的两个双字来存放下界和上界。
(7)ENTER
建立堆栈帧指令
ENTER指令用于过程调用时为便于过程间传递参数而建立堆栈帧所用。
格式:ENTER
imm16,imm8
执行操作:指令中给出地两个操作数均为立即数。第一个操作数为16位立即数,由其指定堆栈帧的大小,即其所占据的字节数。第二个操作数为8位立即数,它给出过程的嵌套层数,此数范围应为0~31。
该指令完成以下操作:
①PUSH(BP)或PUSH(EBP),以保存该寄存器的原始内容。
②(BP)←(SP)或(EBP)←(ESP),使BP或EBP寄存器保存当前堆栈指针SP或ESP的内容,以便在过程运行期间,以BP(或EBP)为基准访问堆栈帧中存放的变量。
③(BP)←(SP)-imm16
或
(EBP)←(ESP)-imm16,这样就建立了堆栈帧所占有的存储空间。
(8)LEAVE
释放堆栈帧指令
LEAVE指令在程序中位于退出过程的RET指令之前,用来释放由ENTER指令建立的堆栈帧存储区。
格式:LEAVE
执行操作:
①(SP)←(BP)或(ESP)←(ESP)
②(BP)←POP()或(EBP)←POP()