5.2.指令系统1

内容分享7小时前发布 炫66666
0 0 0

指令系统是CPU指令的集合,CPU除了具有计算功能的指令外,还有实现其它功能的指令,也有为某种特殊的应用而增设的指令。

通常,把指令按其功能分成以下几大类:

数据传送指令 循环指令

标志位操作指令 转移指令

算术运算指令 条件设置字节指令

逻辑运算指令 字符串操作指令

移位操作指令 ASCII-BCD码运算调整指令

位操作指令 处理器指令

比较运算指令

下面,我们逐一介绍每类指令中的指令。

5.2.1 数据传送指令 

数据传送指令又分为:传送指令、交换指令、地址传送指令、堆栈操作指令、转换指令和I/O指令等。

除了标志位操作指令SAHF和POPF指令外,本类的其它指令都不影响标志位。

1、传送指令MOV(Move Instruction)

传送指令是使用最频繁的指令,它相对于高级语言里的赋值语句。指令的格式如下:

MOV  Reg/Mem, Reg/Mem/Imm

其中:Reg—Register(寄存器),Mem—Memory(存储器),Imm—Immediate(立即数),它们可以是8位、16位或32位(特别指出其位数的除外)。在本网络课件的网页中,都将采用上述缩写,此后不再说明。

指令的功能是把源操作数(第二操作数)的值传给目的操作数(第一操作数)。指令执行后,目的操作数的值被改变,而源操作数的值不变。在存储单元是该指令的一个操作数时,该操作数的寻址方式可以是任意一种存储单元寻址方式。

下面列举几组正确的指令例子:

源操作数是寄存器

MOV  CH, AL MOV  BP, SP MOV  ECX, EBX

MOV  DS, AX MOV  [BX], CH MOV  [BX+SI], AX

源操作数是存储单元

MOV  AL, [100H] MOV  BX, ES:[DI] MOV  EDX, [BX]

MOV  BX, VARW MOV  AX, [BX+SI] MOV  CH, [BX+DI+100H]

其中:VARW是字类型内存变量(下同)。

源操作数是立即数

MOV  AL, 89H MOV  BX, -100H MOV  EDX, 12345678H

MOV  VARW, 200H MOV  [BX], 2345H MOV  [BX+DI], 1234H

在汇编语言中,主要的数据传送方式如图5.1所示。虽然一条MOV指令能实现其中大多数的数据传送方式,但也存在MOV指令不能实现的传送方式。

对MOV指令有以下几条具体规定,其中有些规定对其它指令也同样有效。

1)、两个操作数的数据类型要相同,要同为8位、16位或32位;如:MOV  BL, AX等是不正确的;

2)、两个操作数不能同时为段寄存器,如:MOV  ES, DS等;

3)、代码段寄存器CS不能为目的操作数,但可作为源操作数,如:指令MOV  CS, AX等不正确,但指令MOV  AX, CS等是正确的;

4)、立即数不能直接传给段寄存器,如:MOV  DS, 100H等;

5)、立即数不能作为目的操作数,如:MOV  100H, AX等;

6)、指令指针IP,不能作为MOV指令的操作数;

7)、两个操作数不能同时为存储单元,如:MOV  VARA, VARB等,其中VARA和VARB是同数据类型的内存变量。

对于规定2、4和7,我们可以用通用寄存器作为中转来达到最终目的。表5.1列举一个可行的解决方案,尽供参考。读者可考虑用其它办法来完成同样的功能。

表5.1 MOV指令的变通方法 

功能描述 不正确的指令 可选的解决方法

把DS的值传送给ES MOV  ES, DS MOV  AX, DS MOV  ES, AX

把100H传给DS MOV  DS, 100H MOV  AX, 100H MOV  DS, AX

把字变量VARB的值传送给字变量

VARA MOV  VARA, VARB MOV  AX, VARB MOV  VARA, AX

对于情况1:不同位数数据之间的传送问题,在80386及其以后的CPU中,增加一组新的指令——传送-填充指令,它可把位数少的源操作数传送给位数多的目的操作数,多出的部分按指令的规定进行填充。

2、传送—填充指令(Move-and-Fill Instruction)

传送—填充指令是把位数短的源操作数传送给位数长的目的操作数。指令格式如下:

MOVSX/MOVZX  Reg/Mem, Reg/Mem/Imm     ;80386+

其中:80386+表示80386及其之后的CPU,其它类似符号含义类同,不再说明。

指令的主要功能和限制与MOV指令类似,不同之处是:在传送时,对目的操作数的高位进行填充。根据其填充方式,又分为:符号填充和零填充。

符号填充指令MOVSX(Move with Sign-Extend)

MOVSX的填充方式是:用源操作数的符号位来填充目的操作数的高位数据位。

零填充指令MOVZX(Move with Zero-Extend)

MOVZX的填充方式是:恒用0来填充目的操作数的高位数据位。

3、交换指令XCHG(Exchange Instruction)

交换指令XCHG是两个寄存器,寄存器和内存变量之间内容的交换指令,两个操作数的数据类型要相同。其指令格式如下:

XCHG  Reg/Mem, Reg/Mem

该指令的功能和MOV指令不同,后者是一个操作数的内容被修改,而前者是两个操作数都会发生改变。寄存器不能是段寄存器,两个操作数也不能同时为内存变量。

4、取有效地址指令LEA(Load Effective Address)

指令LEA是把一个内存变量的有效地址送给指定的寄存器。其指令格式如下:

LEA Reg, Mem

该指令通常用来对指针或变址寄存器BX、DI或SI等置初值之用。

BUFFER DB  100 DUP(?)

LEA BX, BUFFER     ;把字节变量BUFFER在数据段内的偏移量送给BX

 

5、取段寄存器指令(Load Segment Instruction)

该组指令的功能是把内存单元的一个“低字”传送给指令中指定的16位寄存器,把随后的一个“高字”传给相应的段寄存器(DS、ES、FS、GS和SS)。其指令格式如下:

LDS/LES/LFS/LGS/LSS Reg, Mem

指令LDS(Load Data Segment Register)和LES(Load Extra Segment Register)在8086CPU中就存在,而LFS和LGS(Load Extra Segment Register)、LSS(Load Stack Segment Register)是80386及其以后CPU中才有的指令。

若Reg是16位寄存器,那么,Men必须是32位指针;若Reg是32位寄存器,那么,Men必须是48位指针,其低32位给指令中指定的寄存器,高16位给指令中的段寄存器。

例如:

POINTER DD 12345678H

LDS BX, POINTER

各寄存器的内容分别为:(BX)=5678H,(DS)=1234H。

 

下面控件是学习和掌握MOV、MOVSX/MOVZX、XCHG、LEA、LDS/LES/LFS/LGS/LSS指令的,它可检查用户输入这些指令的合法性,并对合法的指令显示其执行的结果。

注意:如果指令中含有表示内存单元的寻址方式,那么其控件中的”内存单元的类型”即表示该指令中内存单元的数据类型。

6、堆栈操作指令(Stack Operation Instruction)

堆栈是一个重要的数据结构,它具有“先进后出”的特点,通常用来保存程序的返回地址。它主要有两大类操作:进栈操作和出栈操作。

1)进栈操作

PUSH(Push Word or Doubleword onto Stack)

指令格式:PUSH Reg/Mem

PUSH Imm          ;80286+

一个字进栈,系统自动完成两步操作:SP←SP-2,(SP)←操作数; 

一个双字进栈,系统自动完成两步操作:ESP←ESP-4,(ESP)←操作数。 

PUSHA(Push All General Registers)

指令格式:PUSHA       ;80286+

其功能是依次把寄存器AX、CX、DX、BX、SP、BP、SI和DI等压栈。

PUSHAD(Push All 32-bit General Registers)

指令格式:PUSHAD       ;80386+

其功能是把寄存器EAX、ECX、EDX、EBX、ESP、EBP、ESI和EDI等压栈。

2)出栈操作

POP(Pop Word or Doubleword off Stack)

指令格式:POP Reg/Mem

弹出一个字,系统自动完成两步操作:操作数←(SP),SP←SP-2; 

弹出一个双字,系统自动完成两步操作:操作数←(ESP),ESP←ESP-4。 

POPA(Pop All General Registers)

指令格式:POPA       ;80286+

其功能是依次把寄存器DI、SI、BP、SP、BX、DX、CX和AX等弹出栈。其实,程序员不用记住它们的具体顺序,只要与指令PUSHA对称使用就可以了。

POPAD(Pop All 32-bit General Registers)

指令格式:POPAD      ;80386+

其功能是依次把寄存器EDI、ESI、EBP、ESP、EBX、EDX、ECX和EAX等弹出栈,它与PUSHAD对称使用即可。

7、转换指令XLAT(Translate Instruction)

转换指令有两个隐含操作数BX和AL。指令格式如下:

XLAT/XLATB

其功能是把BX的值作为内存字节数组首地址、下标为AL的数组元素的值传送给AL。其功能描述的表达式是:AL←BX[AL]。

8、I/O指令

有关I/O指令将在第8.1.2节——I/O指令——中介绍,在此从略。

5.2.2 标志位操作指令

标志位操作指令是一组对标志位置位、复位、保存和恢复等操作的指令。

1、进位CF操作指令

清进位指令CLC(Clear Carry Flag):CF←0

 置进位指令STC(Set Carry Flag):CF←1

 进位取反指令CMC(Complement Carry Flag):CF←not CF

2、方向位DF操作指令

清方向位指令CLD(Clear Direction Flag):DF←0

 置方向位指令STD(Set Direction Flag):DF←1

3、中断允许位IF操作指令

清中断允许位指令CLI(Clear Interrupt Flag):IF←0其功能是不允许可屏蔽的外部中断来中断其后程序段的执行。

置中断允许位指令STI(Set Interrupt Flag):IF←1其功能是恢复可屏蔽的外部中断的中断响应功能,通常是与CLI成对使用的。

4、取标志位操作指令

LAHF(Load AH from Flags):AH←Flags的低8位

 SAHF(Store AH in Flags):Flags的低8位←AH

5、标志位堆栈操作指令

PUSHF/PUSHFD(Push Flags onto Stack):把16位/32位标志寄存器进栈;

POPF/POPFD(Pop Flags off Stack):把16位/32位标志寄存器出栈;

5.2.3 算术运算指令

算术运算指令是反映CPU计算能力的一组指令,也是编程时经常使用的一组指令。它包括:加、减、乘、除及其相关的辅助指令。

该组指令的操作数可以是8位、16位和32位(80386+)。当存储单元是该类指令的操作数时,该操作数的寻址方式可以是任意一种存储单元寻址方式。

1、加法指令

加法指令ADD(ADD Binary Numbers Instruction)

指令的格式:ADD  Reg/Mem, Reg/Mem/Imm

受影响的标志位:AF、CF、OF、PF、SF和ZF

指令的功能是把源操作数的值加到目的操作数中。

带进位加指令ADC(ADD With Carry Instruction)

指令的格式:ADC  Reg/Mem, Reg/Mem/Imm

受影响的标志位:AF、CF、OF、PF、SF和ZF

指令的功能是把源操作数和进位标志位CF的值(0/1)一起加到目的操作数中。

加1指令INC(Increment by 1 Instruction)

指令的格式:INC  Reg/Mem

受影响的标志位:AF、OF、PF、SF和ZF,不影响CF

指令的功能是把操作数的值加1。

交换加指令XADD(Exchange and Add)

指令的格式:XADD  Reg/Mem, Reg      ;80486+

受影响的标志位:AF、CF、OF、PF、SF和ZF

指令的功能是先交换两个操作数的值,再进行算术“加”法操作。

方法1:用16位寄存器编写程序

MOV AX, word ptr d1 ;由于d1是双字类型,必须使用强制类型说明符。以下同。

MOV DX, word ptr d1+2 ;(DX,AX)构成一个32位数据

ADD AX, word ptr d2 ;低字相加

ADC DX, word ptr d2+2 ;高字相加。在低字相加时,有可能会产生“进位”

MOV word ptr d1, AX ;低字送给d1的低字

MOV word ptr d1+2, DX ;高字送给d1的高字

方法2:用32位寄存器编写程序

MOV EAX, d1

ADD EAX, d2

MOV d1, EAX

从上面两段程序不难看出:用32位寄存器来处理32位数据显得简单、明了,而16位微机虽然也能处理32位数据,但做起来就要复杂一些。

下面是学习和掌握加法类指令的控件,可模拟执行ADD、ADC、INC、XADD、CLC、STC和CMC等指令。用鼠标左键单击寄存器列表框中指定的寄存器,则可修改其值。后面其它控件的有关操作与此相一致,不再说明。

2、减法指令

减法指令SUB(Subtract Binary Values Instruction)

指令的格式:SUB  Reg/Mem, Reg/Mem/Imm

受影响的标志位:AF、CF、OF、PF、SF和ZF

指令的功能是从目的操作数中减去源操作数。

带借位减SBB(Subtract with Borrow Instruction)

指令的格式:SBB  Reg/Mem, Reg/Mem/Imm

受影响的标志位:AF、CF、OF、PF、SF和ZF

指令的功能是把源操作数和标志位CF的值从目的操作数中一起减去。

减1指令DEC(Decrement by 1 Instruction)

指令的格式:DEC  Reg/Mem

受影响的标志位:AF、OF、PF、SF和ZF,不影响CF

指令的功能是把操作数的值减去1。

求补指令NEG(Negate Instruction)

指令的格式:NEG  Reg/Mem

受影响的标志位:AF、CF、OF、PF、SF和ZF

指令的功能:操作数=0-操作数,即改变操作数的正负号。

例5.4 已知有二个32位数d1和d2,编写程序片段从d1中减去d2的值。

解:

方法1:用16位寄存器编写程序

MOV AX, word ptr d1 ;取低字

MOV DX, word ptr d1+2 ;取高字,(DX,AX)构成一个32位数据

SUB AX, word ptr d2 ;低字相减

SBB DX, word ptr d2+2 ;高字相减。在低字相减时,有可能会产生“借位”

MOV word ptr d1, AX ;低字送给d1的低字

MOV word ptr d1+2, DX ;高字送给d1的高字

方法2:用32位寄存器编写程序

MOV EAX, d1

SUB EAX, d2

MOV d1, EAX

下面是学习和掌握减法类指令的控件,可模拟执行SUB、SBB、DEC、NEG、CLC、STC和CMC等指令。

3、乘法指令

计算机的乘法指令分为无符号乘法指令和有符号乘法指令,它们的唯一区别就在于:数据的最高位是作为“数值”参与运算,还是作为“符号位”参与运算。

乘法指令的被乘数都是隐含操作数,乘数在指令中显式地写出来。CPU会根据乘数是8位、16位,还是32位操作数,来自动选用被乘数:AL、AX或EAX。

指令的功能是把显式操作数和隐含操作数相乘,并把乘积存入相应的寄存器中。

无符号数乘法指令MUL(Unsigned Multiply Instruction)

指令的格式:MUL  Reg/Mem

受影响的标志位:C

 

© 版权声明

相关文章

暂无评论

none
暂无评论...