经典语录

涛涛经典语录

1.知道你一直瞧不起我,这次我要证明给你看,你瞧不起我是多么的正确。

2.知己知彼,方能百战不胜。

3.这么优秀的小伙去哪个坟墓里挖啊。

4.这是狐狸露出狗尾巴了吧。

5.你笨的真有出息。

6.您可真是贱人多忘事啊。

7.我对你将来的坟墓发誓,我说的都是真的。

8.狼牙山五……三五,三五一十五。

9.怎么就不相信我呢,我是真心实意的给你开玩笑呢。

10.您放心,我一定会好好的教他们学坏的。

11.妈呀,他们经常骂我,严重的时候他们骂我骂的都不知道自己姓什么了。

12.我可以很确切的告诉你,这个事好像是对的。

经典语录

 

第二篇:汇编语言_入门经典教材-230页 汇编入门(7 讲)

汇编入门(7 讲)

时间:2009-5-16 8:12:26

核心提示:第 5 章微机CPU 的指令系统指令系统确定了CPU 所能完成的功能,是用 汇编语言进行程序设计的最基本部分。如果不熟悉汇编指令的功能及其有关规定,那么,肯 定不能灵活运用汇编语言。所以,本章的内容是学习本课程的重点和难点。5.1 汇编语言 指令格式为了介绍指令系统中指令的功能,先要清楚汇编语言是如何书写指令的...

第5章微机CPU的指令系统

指令系统确定了CPU 所能完成的功能,是用汇编语言进行程序设计的最基本部分。如 果不熟悉汇编指令的功能及其有关规定,那么,肯定不能灵活运用汇编语言。所以,本章的 内容是学习本课程的重点和难点。

5.1 汇编语言指令格式

为了介绍指令系统中指令的功能,先要清楚汇编语言是如何书写指令的,这就象在学习 高级语言程序设计时,要清楚高级语言语句的语义、语法及其相关规定一样。

5.1.1 指令格式

汇编语言的指令格式如下:

指令助忆符 [ 操作数1 [, 操作数2 [, 操作数3]]] [; 注释]

指令助忆符体现该指令的功能,它对应一条二进制编码的机器指令。指令的操作数个数 由该指令的确定,可以没有操作数,也可以有一个、二个或三个操作数。绝大多数指令的操 作数要显式的写出来,但也有指令的操作数是隐含的,不需要在指令中写出。 当指令含有操作数,并要求在指令中显式地写出来时,则在书写时必须遵守: 指令助忆符和操作数之间要有分隔符,分隔符可以是若干个空格或TAB 键; 如果指令含有多个操作数,那么,操作数之间要用逗号"," 分开。

指令后面还可以书写注释内容,不过,要在注释之前书写分号";"。

5.1.2了解指令的几个方面

在学习汇编指令时,指令的功能无疑是我们学习和掌握的重点,但要准确、有效地运用 这些指令,我们还要熟悉系统对每条指令的一些规定或约束。

归纳起来,对指令还要掌握以下几个方面内容:

、要求指令操作数的寻址方式;

、指令对标志位的影响、标志位对指令的影响;

、指令的执行时间,对可完成同样功能的指令,要选用执行时间短的指令(见附 录2 )。

5.2、指令系统

指令系统是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]

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

源操作数是立即数

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) 、两个操作数不能同时为存储单元,如:M O V VA R A , VA R B等,其中VA R A 和VA R B

是同数据类型的内存变量。

对于规定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

把字变量VA R B 的值传送

给字变量VA R A

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指令类似,不同之处是:在传送时,对目的操作数的高 位进行填充。根据其填充方式,又分为:符号填充和零填充。

传送—填充指令的功能如图5.2所示。

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

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

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

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

例5.1 已知:AL=87H,指令 MOVSX CX, AL ,MOVZX DX, AL执行后,问CX和DX 的值是什么?

解:根据传送-填充指令的填充方式可知:

指令MOVSX CX, AL 执行后,(CX)=0FF87H ,指令MOVZX DX, AL 执行后,

(DX)=0087H 。

从上例可看出,两条指令的源操作数完全一样,但因为它们的填充方式不同,所得到的 结果而就不同。

试比较下列指令,分析它们执行结果的相同和不同之处:

MOV AX, 87H MOVSX AX, 87H MOVZX AX, 87H

3 、交换指令XCHG(Exchange Instruction)

交换指令XCHG 是两个寄存器,寄存器和内存变

量之间内容的交换指令,两个操作数的数据类型要相

同。其指令格式如下:

XCHG Reg/Mem, Reg/Mem

该指令的功能和MOV指令不同,后者是一个操作

数的内容被修改,而前者是两个操作数都会发生改变。

寄存器不能是段寄存器,两个操作数也不能同时为内存

变量。

XCHG 指令的功能如图5.3所示。

例5.2 已知:AX=5678H ,BX=1234H ,指令 XCHG AX, BX执行后,AX和BX的值是什 么?

解:这是两个寄存器内容进行交换,指令执行后,有:(AX)=1234H ,(BX)=5678H 。

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

指令LEA 是把一个内存变量的有效地址送给指定的寄存

器。其指令格式如下:

LEA Reg, Mem

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

值之用。其功能如右图所示。

例如:

?

BUFF

ER

DB 100 DUP(?)

?

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

?

问题:指令“LEA BX BUFFER”和“MOV BX, OFFSET BUFFER”的执行效果是一样的 吗?指令“LEA BX,[BX+200]”和“MOV BX,OFFSET [BX+200]”二者都正确吗?

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位给指令中的段寄存器。指令的执

行结果如图5.5所示。

例如:

?

POINTER DD 12345678H

?

LDS BX, POINTER

?

指令的执行结果如图5.5所示。各寄存器的内容分别为:(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],其功能示意图如图5.6所示。

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 位标志寄存器出栈; 6 、逻辑操作指令的小结

下面是学习标志位指令的控件,浏览者可以运用此类指令,观看标志寄存器的相应变化。

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

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

例5.3 已知有二个32位数d1 和d2(用数据类型 DD说明),编写程序片段把d2 的值加到d1 中。

解:32位数d1 和d2 在内存中如下所示。

?

?

?

?

……

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

MO

V

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

MO

V

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

AD

D

AX, word ptr d2 ; 低字相加

AD

C

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

MO

V

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

MO

V

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

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

MO

V

EAX, d1

AD

D

EAX, d2

MO

V

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 位寄存器编写程序

MO

V

AX, word ptr d1 ; 取低字

MO

V

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

SUB AX, word ptr d2 ;低字相减

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

V

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

MO

V

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

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

MO

V

EAX, d1

SUB EAX, d2

MO

V

d1, EAX

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

3 、乘法指令

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

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

指令的功能是把显式操作数和隐含操作数相乘,并把乘积存入相应的寄存器中。 、无符号数乘法指令MUL(Unsigned Multiply Instruction)

指令的格式:MUL Reg/Mem

受影响的标志位:CF和OF(AF 、PF、SF和ZF无定义)

指令的功能是把显式操作数和隐含操作数(都作为无符号数) 相乘,所得的乘积按表

5.2的对应关系存放。

表5.2 乘法指令中乘数、被乘数和乘积的对应关系

乘数位数隐含的被乘数乘积的存放位置举例

8 位 AL AX MUL BL

16位 AX DX-AX MUL BX

32位 EAX EDX-EAX MUL ECX

、有符号数乘法指令IMUL(Signed Integer Mu ltiply Instruction)

IMU

L

Reg/Mem

IMU

L

Reg, Imm ;80286+

IMU

L

Reg, Reg, Imm ;80286+

指令的格

式:

IMU

L

Reg, Reg/Mem ;80386+

受影响的标志位:CF和OF(AF 、PF、SF和ZF无定义)

1) 、指令格式1——该指令的功能是把显式操作数和隐含操作数相乘,所得的乘积按表

5.2的对应关系存放。

2) 、指令格式2——其寄存器必须是16位/32 位通用寄存器,其计算方式为: Reg ← Reg × Imm

3) 、指令格式3——其寄存器只能是16位通用寄存器,其计算方式为:

Reg1

← Reg

2

×Imm 或 Reg

1

← Mem×Imm

4) 、指令格式4——其寄存器必须是16位/32 位通用寄存器,其计算方式为: Reg1

← Reg

1

×Reg

2

或 Reg

1

← Reg

1

×Mem

在指令格式2~4 中,各操作数的位数要一致。如果乘积超过目标寄存器所能存储的范围, 则系统将置溢出标志OF为1 。

下面是学习和掌握乘法类指令的控件,可模拟执行MUL和IMUL 等指令。

4 、除法指令

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

除法指令功能是用显式操作数去除隐含操作数,可得到商和余数。当除数为0 ,或商超 出数据类型所能表示的范围时,系统会自动产生0 号中断。

、无符号数除法指令DIV(Unsigned Divide Instruction)

指令的格式:DIV Reg/Mem

指令的功能是用显式操作数去除隐含操作数(都作为无符号数),所得商和余数按表

5.3的对应关系存放。指令对标志位的影响无定义。

、有符号数除法指令IDIV(Signed Integer Di vide Instruction)

指令的格式:IDIV Reg/Mem

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

指令的功能是用显式操作数去除隐含操作数(都作为有符号数),所得商和余数的对应关 系见表5.3。

表5.3 除法指令除数、被除数、商和余数的对应关系

除数位数隐含的被除数商余数举例

8 位 AX AL AH DIV BH

16位 DX-AX AX DX DIV BX

32位 EDX-EAX EAX EDX DIV ECX

5 、类型转换指令

在作有符号除法时,有时需要把短位数的被除数转换成位数更长的数据类型。比如,要 用BL中的数据去除 AL,但根据除法指令的规定:除数是8 位,则被除数必须是 AX,于是 就涉及到AH的取值问题。

为了方便说明,假设:(AH)=1H ,(AL)=90H=-112D ,(BL)=10H。

1) 、在作除法运算前,必须处理AH的原有内容

假设在作除法时,不管AH 中的值,这时,(AH 、AL)/BL的商是19H ,但我们知道:

AL/BL 的商应是-7 ,这就导致:计算结果不是所预期的结果,所以,在作除法运算前,程序

员必须要处理AH中的值。

2) 、作无符号数除法时

可强置AH的值为0 ,于是,可得到正确的结果。

3) 、作有符号数除法时

如果强置AH为0 ,则AX=0090H ,这时,AX/BL的商为9 ,显然结果也不正确。 如果把AL的符号位1 ,扩展到 AH中,得:AX=0FF90H=-112D,这时,AX/BL的商就 是我们所要的正确结果。

综上所述,因为在进行有符号数除法时存在隐含操作数数据类型转换的问题,所以,系 统提供了四条数据类型转换指令:CBW、CWD、CWDE 和CDQ。

、字节转换为字指令CBW(Convent Byte to Word)

指令的格式:CBW

该指令的隐含操作数为AH 和AL。其功能是用AL的符号位去填充AH,即:当

AL为正数,则AH=0,否则,AH=0FFH。

指令的执行不影响任何标志位。

、字转换为双字指令CWD(Convent Word to Doubleword)

指令的格式:CWD

该指令的隐含操作数为DX 和AX,其功能是用AX 的符号位去填充DX。指令的

执行不影响任何标志位。

、字转换为扩展的双字指令CWDE(Convent Word to Extended Doubleword)

指令的格式:CWDE ;80386+

该指令的隐含操作数为DX和AX,其功能是用AX的符号位填充EAX的高字位。

指令的执行不影响任何标志位。

、双字转换为四字指令CDQ(Convent Doubleword to Quadword)

指令的格式:CDQ ;80386+

该指令的隐含操作数为EDX和EAX,指令的功能是用EAX的符号位填充EDX。

指令的执行不影响任何标志位。

下面是学习和掌握除法类指令的控件,可模拟执行 DIV 、IDIV、CBW、CWD、CWDE 和CDQ等指令。

例5.5 编写程序段,完成下面计算公式,并把所得的商和余数分别存入 X 和Y 中(其中:

A ,

B ,C ,X 和Y 都是有符号的字变量)。

(C - 120 + A*B) / C

解:

?

A DW ?

B DW ?

C DW ?

X DW ?

Y DW ?

?

MO

V

AX, C

SUB AX, 120D ;书写指令“ADD AX, -120D”也可以

CWD

MO

V

CX, DX

MO

V

BX, AX ;(CX, BX)←(DX, AX) ,调度寄存器,为作乘法准备必要的寄存器

MO

V

AX, A

IMU

L

B ;(DX, AX) ←A*B

AD

D

AX, BX ;计算32位二进制之和,为作除法作准备

AD

C

DX, CX

IDI

V

C ;AX是商,DX是余数

MO X, AX ;分别保存商和余数到指定的字变量单元里

V

MO

V

Y, DX

?

汇编入门(8 讲)

时间:2009-5-16 8:19:24

核心提示:5.2.4 逻辑运算指令逻辑运算指令是另一组重要的指令,它包括:逻辑与

(AND) 、逻辑或(OR)、逻辑非(NOT) 和异或指令(XOR) ,逻辑运算指令也是经常使用的指令。 1 、逻辑与操作指令AND(Logical AND Instruction) 指令的格式:AND Reg/Mem, Reg/Mem/Im...

5.2.4 逻辑运算指令

逻辑运算指令是另一组重要的指令,它包括:逻辑与(AND)、逻辑或(OR)、逻辑非(NOT) 和异或指令(XOR),逻辑运算指令也是经常使用的指令。

1 、逻辑与操作指令AND(Logical AND Instruction)

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

受影响的标志位:CF(0)、OF(0)、PF、SF和ZF(AF 无定义)

指令的功能是把源操作数中的每位二进制与目的操作数中的相应二进制进行逻辑 “与操作”,操作结果存入目标操作数中。

例5.6 已知(BH)=67H ,要求把其的第0、1 和5 位置为0 。

解:可以构造一个立即数,其第0 、1和5 位的值为0 ,其它位的值

为1 ,该立即数即为:0DCH 或11011100B ,然后用指令"AND

BH, 0DCH "来实现此功能。

其计算过程如右图所示。

2 、逻辑或操作指令OR(Logical OR Instruction)

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

受影响的标志位:CF(0)、OF(0)、PF、SF和ZF(AF 无定义)

指令的功能是把源操作数中的每位二进制与目的操作数中的相应二进制进行逻辑" 或操作",操作结果存入目标操作数中。

例5.7 已知(BL)=46H,要求把其的第1、3 、4 和6 位置为1 。

解:构造一个立即数,使其第1 、3 、4 和6 位的值为1 ,其它位的

值为0 ,该立即数即为:5AH 或01011010B ,然后用指令"OR

BL, 5AH"来实现此功能。

其计算过程如右图所示。

3 、逻辑非操作指令NOT(Logical NOT Instruction)

指令的格式:NOT Reg/Mem

其功能是把操作数中的每位变反,即:1 ←0 ,0←1 。指令的执行不影响任何标志位。 例5.8 已知(AL)=46H,执行指令“NOT AL”后,AL的值是什么?

解:执行该指令后,(AL)=0B9H 。其计算过程如下所示。

4 、逻辑异或操作指令XOR(Exclusive OR Instruction)

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

受影响的标志位:CF(0)、OF(0)、PF、SF和ZF(AF 无定义)

指令的功能是把源操作数中的每位二进制与目的操作数中的相应二进制进行逻辑" 异或操作",操作结果存入目标操作数中。

例5.9 已知(AH)=46H ,要求把其的第0、2 、5 和7 位的二进制值变反。

解:构造一个立即数,使其第0 、2 、5 和7 位的值为1 ,其它位的

值为0 ,该立即数即为:0A5H 或10100101B ,然后再用指令

"XOR AH, 0A5H"来实现此功能。

其计算过程如右图所示。

5 、逻辑操作指令的小结

下面是学习和掌握逻辑类指令的控件,可模拟执行AND、OR、NOT和XOR等指令。

5.2.5 移位操作指令

移位操作指令是一组经常使用的指令,它包括算术移位、逻辑移位、双精度移位、循环 移位和带进位的循环移位等五大类。

移位指令都有指定移动二进制位数的操作数,该操作数可以是立即数或 CL的值。在8086 中,该立即数只能为1 ,但在其后的 CPU 中,该立即数可以是1··31之内的数。

1、算术移位指令

算术移位指令有:算术左移SAL(Shift Algebraic Left)和算术右移SAR (Shift Algebraic Right)。它们的指令格式如下:

SAL/SAR Reg/Mem, CL/Imm

受影响的标志位:CF、OF、PF、SF和ZF(AF 无定义)。

算术移位指令的功能描述如下,具体功能下图(a)、(b)所示。

算术左移SAL 把目的操作数的低位向高位移,空出的低位补0 ;

算术右移 SAR 把目的操作数的高位向低位移,空出的高位用最高位(符号位)填补。

例5.10 已知(AH)=12H ,(BL)=0A9H ,试给出分别用算术左移和右移指令移动1 位后,寄存 器AH和BL的内容。

解:用算术左移和右移指令移动1 位后,寄存器 AH和BL的结果如下表所示。 操作数的初值执行的指令执行后操作数的内容

(AH)=12H SAL AH, 1 (AH)=24H

(BL)=0A9H SAL BL, 1 (BL)=52H

(AH)=12H SAR AH, 1 (AH)=09H

(BL)=0A9H SAR BL, 1 (BL)=0D4H

下面是学习和理解算术移位指令的控件。它简单、直观地表达了该移位指令的功能,通 过它,学习者可准确地掌握计算机系统中该移位指令的含义。

在该控件中,操作者可随机生成第一操作数,也可自行输入之。为了便于比较,在执行

指令前,把原操作数的内容存入“操作前的数据”中。

思考题:下面有两组指令序列,问每组指令执行后,寄存器AX的不会变化吗? SAL

AX, 1

SAR

AX, 1

SAR AX, 1

SAL AX, 1

2、逻辑移位指令

此组指令有:逻辑左移 SHL(Shift Logical Left) 和逻辑右移 SHR (Shift Logical Right) 。它 们的指令格式如下:

SHL/SHR Reg/Mem, CL/Imm

受影响的标志位:CF、OF、PF、SF和ZF(AF 无定义)。

逻辑左移/ 右移指令只有它们的移位方向不同,移位后空出的位都补0 。它们的具体功能 下图(a)、(b)所示。

例5.11 已知(AH)=12H ,(BL)=0A9H ,试给出分别用逻辑左移和右移指令移动1 位后,寄存

器AH和BL的内容。

解:用算术左移和右移指令移动1 位后,寄存器 AH和BL的结果如下表所示。 操作数的初值执行的指令

执行后操作数的内

(AH)=12H SHL AH, 1 (AH)=24H

(BL)=0A9H SHL BL, 1 (BL)=52H

(AH)=12H SHR AH, 1 (AH)=09H

(BL)=0A9H SHR BL, 1 (BL)=54H

学习和理解逻辑移位指令的控件。

3、双精度移位指令

此组指令有:双精度左移SHLD(Shift Left Double) 和双精度右移SHRD(Shift Right Double)。它们都是具有三个操作数的指令,其指令的格式如下:

SHLD/SHRD Reg/Mem, Reg, CL/Imm ;80386+

其中:第一操作数是一个16位/32 位的寄存器或存储单元;第二操作数(与前者具有相同 位数)一定是寄存器;第三操作数是移动的位数,它可由CL或一个立即数来确定。

在执行SHLD 指令时,第一操作数向左移n 位,其“空出”的低位由第二操作数的高n 位来填补,但第二操作数自己不移动、不改变。

在执行SHRD 指令时,第一操作数向右移n 位,其“空出”的高位由第二操作数的低n 位来填补,但第二操作数自己也不移动、不改变。

SHLD 和SHRD 指令的移位功能示意图如图5.8所示。

受影响的标志位:CF、OF、PF、SF和ZF(AF 无定义)

下面是几个双精度移位的例子及其执行结果。

双精度移位指令指令操作数的初值指令执行后的结果

SHLD AX, BX, 1 (AX)=1234H ,(BX)=8765H (AX)=2469H

SHLD AX, BX, 3 (AX)=1234H ,(BX)=8765H (AX)=91A4H

SHRD AX, BX, 2 (AX)=1234H ,(BX)=8765H (AX)=448DH

SHRD AX, BX, 4 (AX)=1234H ,(BX)=8765H (AX)=5123H

学习和理解双精度移位指令的控件。

4、循环移位指令

循环移位指令有:循环左移ROL(Rotate Left)和循环右移 ROR(Rotate Right) 。

指令的格式:ROL/ROR Reg/Mem, CL/Imm

受影响的标志位:CF和OF

循环左移/ 右移指令只是移位方向不同,它们移出的位不仅要进入 CF,而且还要填补空 出的位。具体功能如下图(a)、(b)所示。

下面是几个循环移位的例子及其执行结果。

循环移位指令指令操作数的初值指令执行后的结果

ROL AX, 1 (AX)=6789H (AX)=0CF12H

ROL AX, 3 (AX)=6789H (AX)=3C4BH

ROR AX, 2 (AX)=6789H (AX)=59E2H

ROR AX, 4 (AX)=6789H (AX)=9678H

学习和理解不带进位的循环移位指令的控件。

5、带进位的循环移位指令

带进位的循环移位指令有:带进位的循环左移 RCL(Rotate Left Through Carry)和带进位 的循环右移RCR(Rotate Right) 。

指令的格式:RCL/RCR Reg/Mem, CL/Imm

受影响的标志位:CF和OF

带进位的循环左移/右移指令只有移位的方向不同,它们都用原 CF的值填补空出的位, 移出的位再进入CF。具体功能如下图(a)、(b)所示。

下面是几个带进位循环移位的例子及其执行结果。

双精度移动指令指令操作数的初值

指令执行后的结

RCL AX, 1 CF=0,(AX)=0ABCDH (AX)=579AH

RCL AX, 1 CF=1,(AX)=0ABCDH (AX)=579BH

RCR AX, 2 CF=0,(AX)=0ABCDH (AX)=AAF3H

RCR AX, 2 CF=1,(AX)=0ABCDH (AX)=EAF3H

例5.12 编写指令序列把由 DX和AX组成的32位二进制算术左移、循环左移1 位。 解:

(DX,AX) 算术左移1 位指令序列 (DX,AX) 循环左移1 位指令序列

SHL AX, 1

RCL DX, 1

SHLD DX, AX, 1

RCL AX, 1

学习和理解带进位的循环移位指令的控件。

6、移位指令的学习和理解

下面的控件是把各种移位指令的模拟功能组合在一起。它不仅简单、直观地表达了各种 移位指令的功能,而且能通过对照,理解它们之间的区别。该控件还结合了其它指令(CLC 、 STC 和CMC)来增加指令的组合变化。

5.2.6 位操作指令

1 、位扫描指令(Bit Scan Instruction)

指令的格式:BSF/BSR Reg, Reg/Mem ;80386+

受影响的标志位:ZF

位扫描指令是在第二个操作数中找第一个“1”的位置。如果找到,则该“1”的位置保存在 第一操作数中,并置标志位ZF为1,否则,置标志位ZF为0 。

根据位扫描的方向不同,指令分二种:正向扫描指令和逆向扫描指令。

、正向扫描指令BSF(Bit Scan Forward)从右向左扫描,即:从低位向高位扫描;

、逆向扫描指令BSR(Bit Scan Reverse)从左向右扫描,即:从高位向低位扫描。

例如:

MOV AX, 1234H

BSF CX, AX ; 指令执行后,(CX)=2

BSR CX, AX ; 指令执行后,(CX)=12

2 、位检测指令(Bit Test Instruction)

指令的格式:BT/BTC/BTR/BTS Reg/Mem, Reg/Imm ;80386+

受影响的标志位:CF

位检测指令是把第一个操作数中某一位的值传送

给标志位CF,具体的哪一位由指令的第二操作数来确

定。

根据指令中对具体位的处理不同,又分一下几种指

令:

BT:把指定的位传送给CF;

BTC :把指定的位传送给 CF后,还使该位变

反;

BTR :把指定的位传送给 CF后,还使该位变

为0 ;

BTS :把指定的位传送给CF后,还使该位变

为1 ;

图5.11 位检测指令的功能示意图

例如:假设(AX)=1234H ,分别执行下面指令。

BT AX, 2 ; 指令执行后,CF=1,(AX)=1234h

BTC AX, 6 ; 指令执行后,CF=0,(AX)=1274h

BTR AX, 10 ; 指令执行后,CF=0,(AX)=1234h

BTS AX, 14 ; 指令执行后,CF=0,(AX)=5234h

3 、检测位指令 TEST(Test Bits Instruction)

检测位指令是把二个操作数进行逻辑“与”操作,并根据运算结果设置相应的标志位,但 并不保存该运算结果,所以,不会改变指令中的操作数。在该指令后,通常用JE 、JNE 、JZ

和JNZ 等条件转移指令。

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

受影响的标志位:CF(0)、OF(0)、PF、SF和ZF(AF 无定义)

例如:

TEST AX, 1 ; 测试AX的第0 位

TEST CL, 10101B ; 测试CL的第0 、2 、4位

下面是学习和掌握乘法类指令的控件,可模拟执行 BSF 、BSR 、BT、BTC 、BTR 、BTS 和TEST 等指令。

5.2.7 比较运算指令

在程序中,我们要时常根据某个变量或表达式的取值去执行不同指令,从而使程序表现 出有不同的功能。为了配合这样的操作,在CPU 的指令系统中提供了各种不同的比较指令。 通过这些比较指令的执行来改变有关标志位,为进行条件转移提供依据。

1 、比较指令CMP(Compare Instruction)

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

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

指令的功能:用第二个操作数去减第一个操作数,并根据所得的差设置有关标志位, 为随后的条件转移指令提供条件。但并不保存该差,所以,不会改变

指令中的操作数。

2 、比较交换指令(Compare And Exchange Instruction)

在数据传送类指令中,我们介绍了交换指令XCHG ,它不管二个操作数的值是什么,

都无条件地进行交换。而比较交换指令,是先进行比较,再根据比较的结果决定是否进行操 作数的交换操作。

比较交换指令的功能:当二个操作数相等时,置标志位ZF为1 ;否则,把第一操作数 的值赋给第二操作数,并置标志位ZF为0 。

、8 位/16位/32位比较交换指令

指令的格式:CMPXCHG Reg/Mem, AL/AX/EAX ;80486+

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

MASM 6.11中指令的描述与此不同,它没有限定第二操作数的要求。

、64位比较交换指令

该指令只有一个操作数,第二个操作数EDX:EAX 是隐含的。

指令的格式:CMPXCHG8B Reg/Mem ;Pentium+

受影响的标志位:ZF

例如:假设(AX)=1234H ,(BX)=1234H ,(CX)=4321H 。

CMPXCHG BX, AX ; 指令执行后,ZF=1

CMPXCHG CX, AX ; 指令执行后,ZF=0,(AX)=4321H ,CX的值不变

3 、字符串比较指令(Compare String Instruction)

参见后面第5.2.11节——字符串操作类指令——的叙述。

5.2.8 循环指令

循环结构是程序的三大结构之一。为了方便构成循环结构,汇编语言提供了多种循环指 令,这些循环指令的循环次数都是保存在计数器 CX或ECX 中。除了 CX或ECX可以决定 循环是否结束外,有的循环指令还可由标志位ZF来决定是否结束循环。

在高级语言中,循环计数器可以递增,也可递减,但汇编语言中,CX 或ECX只能递 减,所以,循环计数器只能从大到小。在程序中,必须先把循环次数赋给循环计数器。 汇编语言的循环指令都是放在循环体的下面,在循环时,首先执行一次循环体,然后把 循环计数器CX或ECX减1 。当循环终止条件达到满足时,该循环指令下面的指令将是下一 条被执行的指令,否则,程序将向上转到循环体的第一条指令。

在循环未终止,而向上转移时,规定:该转移只能是一个短转移,即偏移量不能超过128, 也就是说循环体中所有指令码的字节数之和不能超过128 。如果循环体过大,可以用后面介

绍的“转移指令”来构造循环结构。

循环指令本身的执行不影响任何标志位。

1 、循环指令(Loop Until Complete)

循环指令LOOP 的一般格式:

LOOP 标号

LOOPW 标号 ;CX作为循环计

数器,80386+

LOOPD 标号 ;ECX 作为循环

计数器,80386+

循环指令的功能描述:

(CX)=(CX)-1 或(ECX)=(ECX)-1 ;

如果(CX)≠0 或(ECX) ≠0 ,转向“标号”所指向的指

令,否则,终止循环,执行该指令下面的指令。

例5.13 编写一段程序,求1+2+?+1000 之和,并把结果存入 AX中。

解:

方法1 :因为计数器 CX只能递减,所以,可把求和式子改变为:1000+999+?+2+1 。 ?

XO

R

AX, AX

MO

V

CX, 1000D

AD

D

AX, CX ;计算过程:1000+999+?+2+1

LOO

P

again

again:

?

方法2 :不用循环计数器进行累加,求和式子仍为:1+2+?+999+1000 。 ?

XO

R

AX, AX

MO

V

CX, 1000D

MO

V

BX, 1

AD

D

AX, BX ;计算过程:1+2+?+999+1000

INC BX

LOO

P

again

again:

?

从程序段的效果来看:方法1 要比方法2 好。

2 、相等或为零循环指令(Loop While Equal or Loop While Zero)

相等或为零循环指令的一般格式:

LOOPE/LOOPZ 标号

LOOPEW/LOOPZW 标号 ;CX 作为循环

计数器,80386+

LOOPED/LOOPZD 标号 ;ECX 作为循

环计数器,80386+

这是一组有条件循环指令,它们除了要受CX 或

ECX的影响外,还要受标志位 ZF的影响。其具体规定

如下:

(1)、(CX)=(CX)-1 或(ECX) =(ECX)-1 ; (不改变

任何标志位)

(2)、如果循环计数器≠0 且ZF=1,则程序转到循环

体的第一条指令,否则,程序将执行该循环指令下面的

指令。

3 、不等或不为零循环指令(Loop While Not Equal or Loop While Not Zero)

不等或不为零循环指令的一般格式:

LOOPNE/LOOPNZ 标号

LOOPNEW/LOOPNZW 标号 ;CX 作为循环

计数器,80386+

LOOPNED/LOOPNZD 标号 ;ECX 作为循

环计数器,80386+

这也是一组有条件循环指令,它们与相等或为零循

环指令在循环结束条件上有点不同。其具体规定如下:

(1)、(CX)=(CX)-1 或(ECX) =(ECX)-1 ; (不改变任

何标志位)

(2)、如果循环计数器≠0 且ZF=0,则程序转到循环体

的第一条指令,否则,程序将执行该循环指令下面的指令。

4 、循环计数器为零转指令(Jump if CX/ECX is Zero)

在前面的各类循环指令中,不管循环计数器的初值为何,循环体至少会被执行一次。

当循环计数器的初值为0时,通常的理解应是循环体被循环0次,即循环体一次也不被执行。 其实不然,循环体不是不被执行,而是会被执行65536 次(用CX计数)或4294967296次(几乎

是死循环,用ECX计数)。

为了解决指令的执行和常规思维之间差异,指令系统又提供了一条与循环计数器有关的 指令——循环计数器为零转指令。该指令一般用于循环的开始处,其指令格式如下: JCXZ 标号 ; 当CX=0时,则程序转移标号处执行

JECXZ 标号 ; 当ECX=0时,则程序转移标号处执行,80386+

例5.14 编写一段程序,求1+2+?+k(K≥0) 之和,并把结果存入AX中。

解:

?

K DB ? ; 变量定义

?

XOR AX, AX

MOV CX, K

JCXZ next

ADD AX, CX ; 计算过程: K+(K-1)+?+2+1 again:

LOO

P

again

next: …

思考题:假设变量 K 的值为0 ,并且在循环体的前面没有写指令“JCXZ next”,这时求出 的“和”AX 的值是什么?

5.2.9 转移指令

转移指令是汇编语言程序员经常使用的一组指令。在高级语言中,时常有“尽量不要使 用转移语句”的劝告,但如果在汇编语言的程序中也尽量不用转移语句,那么该程序要么无 法编写,要么没有多少功能,所以,在汇编语言中,不但要使用转移指令,而且还要灵活 运用,因为指令系统中有大量的转移指令。

转移指令分无条件转移指令和有条件转移指令两大类。

1 、无条件转移指令(Transfer Unconditionally)

无条件转移指令包括:JMP 、子程序的调用和返回指令、中断的调用和返回指令等。 下面只介绍无条件转移指令JMP(Unconditional Jump) 。

JMP 指令的一般形式:

JMP 标号/Reg/Mem

JMP 指令是从程序当前执行的地方无条件转移到另一个地方执行。这种转移可以是一

个短(short)转移(偏移量在[-128, 127] 范围内),近(near) 转移(偏移量在[-32K, 32K] 范围内)或远

(far)转移(在不同的代码段之间转移)。

短和近转移是段内转移,JMP 指令只把目标指令位置的偏移量赋值指令指针寄存器IP , 从而实现转移功能。但远转移是段间转移,JMP 指令不仅会改变指令指针寄存器IP 的值, 而且还会改变代码段寄存器CS的值。

该转移指令的执行不影响任何标志位。

例如:

?

JMP next1 ; 向前转移,偏移量之差为负数

?

JMP next2 ; 向后转移,偏移量之差为正数

next1:

?

next2: …

在目前流行的汇编系统中,当段内转移时,有些软件把该转移指令默认为近转移,从而 使指令的偏移量用一个字来表示,于是生成3 个字节的指令代码,但如果程序员自己清楚转

移的幅度在一个短转移的范围之内,那么,可用前置short的办法来告诉汇编程序,让它产 生2 个字节的指令代码。

比如:如果程序员知道在上例中的标号 next2离“JMP next2”指令的偏移量不会超过127 , 那么,可用下面的转移方式来省掉一个字节的指令代码。

?

JMP short next2 ; 生成2 个字节的转移指令,从而节省一个字节

?

next2:

?

2 、条件转移指令(Transfer Conditionally)

条件转移指令是一组极其重要的转移指令,它根据标志寄存器中的一个(或多个)标志位 来决定是否需要转移,这就为实现多功能程序提供了必要的手段。微机的指令系统提供了丰 富的条件转移指令来满足各种不同的转移需要,在编程序时,要对它们灵活运用。 条件转移指令又分三大类:基于无符号数的条件转移指令、基于有符号数的条件转移指 令和基于特殊算术标志位的条件转移指令。

、无符号数的条件转移指令(Jumps Based on Unsigned (Logic) Data)

指令的助忆符检测的转移条件功能描述

JE/JZ ZF=1 Jump Equal or Jump Zero

JNE/JNZ ZF=0 Jump Not Equal or Jump Not Zero

JA/JNBE CF=0 and ZF=0 Jump Above or Jump Not Below or Equal

JAE/JNB CF=0 Jump Above or Equal or Jump Not Below

JB/JNAE CF=1 Jump Below or Jump Not Above or Equal

JBE/JNA CF=1 or AF=1 Jump Below or Equal or Jump Not Above

、有符号数的条件转移指令(Jumps Based on Signed (Arithmetic) Data)

指令的助忆符检测的转移条件功能描述

JE/JZ ZF=1 Jump Equal or Jump Zero

JNE/JNZ ZF=0 Jump Not Equal or Jump Not Zero

JG/JNLE ZF=0 and SF=OF Jump Greater or Jump Not Less or Equal

JGE/JNL SF=OF Jump Greater or Equal or Jump Not Less

JL/JNGE SF≠OF Jump Less or Jump Not Greater or Equal

JLE/JNG ZF=1 or SF ≠OF Jump Less or Equal or Jump Not Greater

、特殊算术标志位的条件转移指令(Jumps Based on Special Arithmetic Tests)

指令的助忆符检测的转移条件功能描述

JC CF=1 Jump Carry

JNC CF=0 Jump Not Carry

JO OF=1 Jump Overflow

JNO OF=0 Jump Not Overflow

JP/JPE PF=1 Jump Parity or Jump Parity Even

JNP/JPO PF=0 Jump Not Pari ty or Jump Parity Odd

JS SF=1 Jump Sign (negative)

JNS SF=0 Jump No Sign (positive)

例5.15 编写一程序段,它把寄存器 AX-BX的绝对值存入BX中。

解:

? next:

S

U

B

BX, AX

JN

S

next

N

E

G

BX

?

例5.16 已知一个字节变量 char ,试编写一程序段,把其所存的大写字母变成小写字母。 解:

?

cha

r

DB 'F' ;变量说明

?

MO

V

AL, char

CM

P

AL, 'A'

JB next ; 注意:字符是无符号数,不要使用指令JL

CM

P

AL, 'Z'

JA next

AD

D

char, 20H ; 小写字母比大写字母的ASCII 码大20H

next:

?

如果不知道( 或忘了)大小写字母ASCII 码之间的关系,那么,可用数值表达式'a'-'A' 、 'b'-'B' 、?、'z'-'Z'等来代替具体的数值20H 。

例5.17 编写一段程序,完成下面计算公式,其中:变量 X 和Y 都是字类型。 解:

?

X DW ? ;变量说明

Y DW ?

?

MO

V

AX, X

MO BX, AX ;用BX来临时存放计算结果

V

CM

P

AX, 0

JLE setdata

CM

P

AX, 500

JG case3

AD

D

BX, 100D ;BX=X+100

JM

P

setdata

next:

SU

B

BX, 50D ;BX=X-50

MO

V

Y, B X ;把计算结果赋给变量Y

setda

ta:

?

例5.18 下面循环体的指令代码字节数超过128,试改写该循环。 ?

MOV CX,

COUNT

; 给循环计数器赋初值(>0)

循环体指令序列 ;循环体的首地址偏移量大于128 again:

LOOP again

解:

?

MOV CX, COUNT

循环体指令序列

DEC CX

again:

JNZ again ;把LOOP 指令改为条件转移指令

汇编入门(9 讲)

时间:2009-5-16 8:30:04

核心提示:5.2.10 条件设置字节指令条件设置字节指令(Set Byte Conditionally)是80386 及其以后CPU 所具有的一组指令。它们在测试条件方面与条件转移是一致的,但在功能方 面,它们不是转移,而是根据测试条件的值来设置其字节操作数的内容为1 或0 。条件设置

字节指令的一般格式如下:SETnn...

5.2.10 条件设置字节指令

条件设置字节指令(Set Byte Conditionally) 是80386及其以后CPU 所具有的一组指令。它 们在测试条件方面与条件转移是一致的,但在功能方面,它们不是转移,而是根据测试条件 的值来设置其字节操作数的内容为1或0 。

条件设置字节指令的一般格式如下:

SETnn Reg/Mem ;80386+

其中:nn是表示测试条件的(见表5.4) ,操作数只能是8 位寄存器或一个字节单元。 这组指令的执行不影响任何标志位。

表5.4 条件设置字节指令列表

指令的助忆符操作数和检测条件之间的关系

SETZ/SETE Reg/Mem = ZF

SETNZSETNE Reg/Mem = not ZF

SETS Reg/Mem = SF

SETNS Reg/Mem = not SF

SETO Reg/Mem = OF

SETNO Reg/Mem = not OF

SETP/SETPE Reg/Mem = PF

SETNP/SETPO Reg/Mem = not PF

SETC/SETB/SETNAE Reg/Mem = CF

SETNC/SETB/SETAE Reg/Mem = not CF

SETNA/SETBE Reg/Mem = (CF or ZF)

SETA/SETNBE Reg/Mem = not (CF or ZF)

SETL/SETNGE Reg/Mem = (SF xor OF)

SETNL/SETGE Reg/Mem = not (SF xor OF)

SETLE/SETNG Reg/Mem = (SF xor OF) or ZF

SETNLE/SETG Reg/Mem = not ((SF xor OF) or ZF)

例5.19 编写程序段:检测寄存器 EAX的8 个16 进制中有几个0H,并把统计结果存入 BH中。

解:

方法1 :用条件转移指令来实现

XOR BH, BH

MOV CX, 8 ;测试寄存器EAX——8次

TEST AL, 0FH ; 测试低四位二进制是否为0H again:

JNZ next

INC BH

ROR EAX, 4 ; 循环向右移四位,为测试高四位作准备

LOO

P

again

方法2 :用条件设置字节指令来实现

XOR BH, BH

next:

MOV CX, 8 ;测试寄存器EAX——8次

TEST AL, 0FH ; 测试低四位二进制是否为0H

SETZ BL ; 如果AL的低四位是0 ,则 BL置为1,否则,BL为0

ADD BH, BL

ROR EAX, 4

again:

LOO

P

again

5.2.11 字符串操作指令

字符串操作指令的实质是对一片连续存储单元进行处理,这片存储单元是由隐含指针

DS:SI或ES:DI 来指定的。字符串操作指令可对内存单元按字节、字或双字进行处理,并能 根据操作对象的字节数使变址寄存器SI(和DI) 增减1 、2 或4。具体规定如下:

(1)、当DF=0时,变址寄存器SI(和DI)增加1 、2 或4;

(2)、当DF=1时,变址寄存器SI(和DI)减少1 、2 或4。

在后面各指令中,有关变址寄存器都按上述规定进行增减,不再一一说明。

1 、取字符串数据指令(Load String Instruction)

从由指针DS:SI所指向的内存单元开始,取一个字节、字或双字进入AL、AX或EAX 中,并根据标志位DF对寄存器SI 作相应增减。该指令的执行不影响任何标志位。 指令的格式:LODS 地址表达式

LODSB/LODSW

LODSD ;8

0386+

在指令LODS 中,它会根据其地址表达式的属性来

决定读取一个字节、字或双字。即:当该地址表达式的

属性为字节、字或双字时,将从指针DS:SI处读一个字

节到AL中,或读一个字到 AX,或读一个双字到 EAX

中,与此同时,SI 还将分别增减1 ,2 或4 。

其它字符串指令中的“地址表达式”作用与此类似,将不再说明。

2 、置字符串数据指令(Store String Instruction)

该指令是把寄存器AL、AX 或EAX中的值存于

以指针ES:DI 所指向内存单元为起始的一片存储单元

里,并根据标志位 DF对寄存器DI作相应增减。该指

令不影响任何标志位。

指令的格式:STOS 地址表达式

STOSB/STOSW

STOSD ;80386+

3 、字符串传送指令(Move String Instruction)

该指令是把指针DS:SI 所指向的字节、字或双字传送给指针ES:DI 所指向内存单元,并 根据标志位DF对寄存器DI和SI 作相应增减。该指令的执行不影响任何标志位。 指令的格式:MOVS 地址表达式1, 地址表达式2

MOVSB/MOVSW

MOVSD ;80386+

4 、输入字符串指令(Input String Instruction)

该指令是从某一指定的端口接受一个字符串,并存入一片存储单元之中。输入端口由 DX指定,存储单元的首地址和读入数据的个数分别由 ES:DI 和CX来确定。在指令的执行 过程中,还根据标志位DF对寄存器DI作相应增减。该指令不影响任何标志位。 与指令有关的操作数ES、DI、DX和CX等都是隐含操作数。

指令的格式:INS 地址表达式

INSB/INSW

INSD ;80286+

5 、输出字符串指令(Output String Instruction)

该指令是把一个字符串输入到指定的输出端口中。输出端口由 DX指定,其输出数据的 首地址和个数分别由DS:SI和CX来确定。在指令的执行过程中,还根据标志位 DF对寄存 器SI 作相应增减。该指令的执行不影响任何标志位。

与指令有关的操作数DS、SI 、DX和CX等都是隐含操作数。

指令的格式:OUTS 地址表达式

OUTSB/OUTSW

OUTSD ;80286+

6 、字符串比较指令(Compare String Instruction)

该指令是把指针DS:SI 和ES:DI 所指向字节、字或

双字的值相减,并用所得到的差来设置有关的标志位。

与此同时,变址寄存器SI 和DI也将根据标志位DF的

值作相应增减。

指令的格式:CMPS 地址表达式1, 地址表达式

2

CMPSB/CMPSW

CMPSD ;80386+

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

7 、字符串扫描指令(Scan String Instruction)

该指令是用指针ES:DI 所指向字节、字或双字的值与相应的 AL、AX或EAX的值相减, 用所得到的差来设置有关标志位。与此同时,变址寄存器 DI还将根据标志位DF的值进行增

减。

指令的格式:SCAS 地址表达式1

SCASB/SCASW

SCASD ;80386+

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

8 、重复字符串操作指令(Repeat String Instruction)

前面介绍了七种不同的字符串操作指令:取字符串数据、置字符串数据、字符串传送、 输入字符串、输出字符串、字符串比较和字符串扫描等指令,所叙述是这些指令执行一次所 具有的功能。但我们知道:每个字符串通常会有多个字符的,所以,就需要重复执行这些 字符串操作指令。为了满足这种需求,指令系统提供了一组重复前缀指令。

虽然在这些字符串指令的前面都可以添加一个重复前缀指令,但由于指令执行结果的差 异,对某个具体的字符串指令又不用重复前缀指令而改用其它循环来实现重复的需要。 重复字符串操作指令对标志位的影响是由被重复的字符串操作指令来决定。

重复前缀指令REP(Repeat String Instruction)

重复前缀指令是重复其后的字符串操作指令,重复的次数由CX来决定。其一般格式为: REP LODS/LODSB/LODSW/LODSD

REP STOS/STOSB/STOSW/STOSD

REP MOVS/MOVSB/MOVSW/MOVSD

REP INS/ INSB/INSW/INSD

REP OUTS/OUTSB/OUTSW/OUTSD

重复前缀指令的执行步骤如下:

(1)、判断:CX=0;

(2)、如果CX=0,则结束重复操作,执行程序中的下一条指令;

(3)、否则,CX=CX-1(不影响有关标志位),并执行其后的字符串操作指令,在该指 令执行完后,再转到步骤(1)。

从上面的重复前缀指令格式来看,虽然我们可以使用重复取字符串数据指令( 第一组指 令),但可能会因为指令的执行结果而在程序中几乎不被使用。

例5.20 编写一段程序,计算字符串“12345abcdefgh”中字符的ASCII 之和。

解:

?

M

ES

S

DB '12345abcdefgh' ; 在数据段中进行变量说明

?

M

O

V

AX, SEG MESS

M

O

V

DS, AX

LE

A

SI, MESS ; 用DS:SI来指向字符串的首地址

M

O

V

CX, 13D ; 重复次数

X

OR

BX, BX ; 置求和的初值为0

RE

P

LODSB

?

虽然指令“REP LODSB”能从字符串中取出每个字符,但它是在一条指令中完成的,程 序的其它指令根本无法处理每次取出的数据,指令的执行结果是:AL只保存最后一次所取 出的字符'h' 的ASCII 码。

所以,为了实现本例的要求,不能使用重复前缀指令,而要把指令“REP LODSB”改写 成如下四条指令:

X

OR

AH, AH ; 为后面的累加作准备

LODSB

A

D

D

BX, AX ;AL是被取出的字符,AH已被清0

again:

LO

OP

again

条件重复前缀指令(Repeat String Conditionally)

条件重复前缀指令与前面的重复前缀指令功能相类似,所不同的是:其重复次数不仅由 CX来决定,而且还会由标志位 ZF来决定。根据 ZF所起的作用又分为二种:相等重复前缀 指令REPE/REPZ和不等重复前缀指令REPE/REPZ。

A、相等重复前缀指令的一般格式为:

REPE/REPZ SCAS/SCASB/SCASW/SCASD

REPE/REPZ CMPS/CMPSB/CMPSW/CMPSD

该重复前缀指令的执行步骤如下:

(1)、判断条件:CX≠0 且 ZF=1 ;

(2)、如果条件不成立,则结束重复操作,执行程序中的下一条指令;

(3)、否则,CX=CX-1(不影响有关标志位),并执行其后的字符串操作指令,在该指 令执行完后,再转到步骤(1)。

B 、不等重复前缀指令的一般格式为:

REPNE/REPNZ SCAS/SCASB/SCASW/SCASD

REPNE/REPNZ CMPS/CMPSB/CMPSW/CMPSD

该重复前缀指令的执行步骤如下:

(1)、判断条件:CX≠0 且 ZF=0 ;

(2)、如果条件不成立,则结束重复操作,执行程序中的下一条指令;

(3)、否则,CX=CX-1(不影响有关标志位),并执行其后的字符串操作指令,在该指 令执行完后,再转到步骤(1)。

5.2.12 ASCII--BCD 码运算调整指令

前面介绍的算术运算指令都是针对二进制数进行操作的指令,但对绝大多数人来说,十 进制是最简单、熟悉的。为了方便按十进制数进行算术运算,指令系统专门提供了一组十进 制运算调整指令。

虽然人们会觉得按十进制进行算术运算很自然,但计算机要化更多的时间来完成相应操 作。在通常情况下,这组指令很少被程序员运用在实际的程序之中。所以,这组指令的使用 率较低,可以根据需要有选择性地学习。

1 、ASCII 码加调整指令AAA(Ascii Adjust After Addition)

该指令是用于调整AL之值,该值是二个ASCII 码字节相加之和。具体的调整规则如下: 、若 AL的低四位大于9 ,或标志位 AF=1,则,AH=AH+1,AL=AL+6,并置 AF和 CF为1 ,否则,只置 AF和CF为0 ;

、清除AL的高四位。

指令的格式:AAA

受影响的标志位:AF和CF(OF 、PF、SF和ZF等都是无定义)

例5.21 编写一段程序,完成二个15位十进制数X 和Y 之和,并把计算结果存入 X 之中。假

设数据X 和Y 都是以字符串形式表示的。

解:

?

X

db

"456407983123186"

; 任意假设二个15位的大数

Y db "326676709587211"

?

CLC

MO

V

SI, 14 ; 用变址寄存器SI 来从字符串的后面向前访问

MO

V

CX, 15 ; 因为它们是二个15位十进制数

MO

V

AL, X[SI]

loop1:

AD

C

AL, Y[SI] ; 把被加数加上

AAA

MO

V

X[SI], AL

DEC SI

LOO

P

loop1 ;15 位十进制数相加完毕

LEA BX, X ;下面5 条指令是把 X 中的数据变成对应的字符

MO

V

CX, 15

AD

D

byte ptr [BX], '0'

INC BX

LOO

P

loop2

loop2:

?

从上例可以看出,其实任意位的十进制数也都是可以的,只要改变CX的值即可。 2 、ASCII 码减调整指令AAS(Ascii Adjust After Subtraction)

该指令是用于调整AL之值,该值是二个ASCII 码字节相减之差。具体的调整规则如下: 、若AL的低四位大于9,或标志位CF=1,则,AH=AH-1,AL=AL-6,并置AF和 CF为1 ,否则,只置 AF和CF为0 ;

、清除AL的高四位。

指令的格式:AAS

受影响的标志位:AF和CF(OF 、PF、SF和ZF等都是无定义)

3 、ASCII 码乘调整指令AAM(Ascii Adjust After Multiplication)

该指令是用于调整寄存器AL之值,该值是由二个单BCD码字节用无符号乘指令 MUL 所得的积。其调整规则如下:

AH←AL/10( 商),AL←AL%10(余数)

指令的格式:AAM

受影响的标志位:PF、SF和ZF(AF 、CF和OF等都是无定义)

例如:

MOV AL, 9

MOV BL, 8

MUL BL ;AL=72D

AAM ;AH=7, AL=2

4 、ASCII 码除调整指令AAD(Ascii Adjust After Division)

该指令是在作除法前用于调整寄存器AH和AL之值,它是把二个寄存器中单BCD码 组成一个十进制数值,为下面的除法作准备的。其调整规则如下:

AL←AH*10+AL ,AH←0

指令的格式:AAD

受影响的标志位:PF、SF和ZF(AF 、CF和OF等都是无定义)

例如:

MOV AX, 0502H

MOV BL, 10D

AAD ;AH=0, AL=52D

DIV BL ;AH=2(余数), AL=5( 商)

5 、十进制数加调整指令 DAA(Decimal Adjust After Addition)

该指令是用于调整AL的值,该值是由指令 ADD或ADC运算二个压缩型BCD码所得

到的结果。压缩型BCD码是一个字节存放二个 BCD码,低四位和高四位都是一个BCD码。 其调整规则如下:

、如果AL的低四位大于9,或标志位AF=1,那么,AL=AL+6,并置AF=1;

、如果AL的高四位大于9,或CF=1,那么,AL=AL+60H,并置 CF=1;

、如果以上两点都不成立,则,清除标志位AF和CF。

经过调整后,AL的值仍是压缩型BCD码,即:二个压缩型 BCD码相加,并进行调整 后,得到的结果还是压缩型BCD码。

指令的格式:DAA

受影响的标志位:AF、CF、PF、SF和ZF(OF 无定义)

例如:

MOV AL, 43H

MOV BL, 29H

ADD AL, BL ;AL=6BH,其不是压缩型的 BCD码,因为低四位'B'不是

BCD码

DAA ; 调整后,AL=72H,这是压缩型的 BCD码,也有:43+29=72

6 、十进制数减调整指令 DAS(Decimal Adjust After Subtraction)

该指令也是用于调整AL的值,该值是由指令SUB 或SBB 运算二个压缩型BCD码所 得到的结果。其调整规则如下:

、如果AL的低四位大于9,或标志位AF=1,那么,AL=AL-6,并置AF=1;

、如果AL的高四位大于9,或CF=1,那么,AL=AL-60H,并置CF=1;

、如果以上两点都不成立,则,清除标志位AF和CF。

经过调整后,AL的值仍是压缩型BCD码,即:二个压缩型 BCD码相减,并进行调整 后,得到的结果还是压缩型BCD码。

指令的格式:DAS

受影响的标志位:AF、CF、PF、SF和ZF(OF 无定义)

例如:

MOV AL, 43H

MOV BL, 29H

SUB AL, BL ;AL=1AH,其不是压缩型的BCD码,因为低四位'A'不是

BCD码

DAS ; 调整后,AL=14H,这是压缩型的 BCD码,也有:43-29=14

5.2.13 处理器指令

处理器指令是一组控制CPU 工作方式的指令。这组指令的使用频率不高。

1 、空操作指令 NOP(No Operation Instruction)

该指令没有的显式操作数,主要起延迟下一条指令的执行。通常用执行指令“XCHG AX, AX”来代表它的执行。NOP 指令的执行不影响任何标志位。

指令的格式:NOP

2 、等待指令WAIT(Put Processor in Wait State Instruction)

该指令使CPU 处于等待状态,直到协处理器(Coprocessor)完成运算,并用一个重启信 号唤醒CPU 为止。该指令的执行不影响任何标志位。

指令的格式:WA I T

3 、暂停指令HLT(Enter Halt State Instruction)

在等待中断信号时,该指令使CPU 处于暂停工作状态,CS:IP 指向下一条待执行的指

令。当产生了中断信号,CPU 把CS和IP 压栈,并转入中断处理程序。在中断处理程序执 行完后,中断返回指令IRET 弹出IP 和CS,并唤醒CPU 执行下条指令。

指令的格式:HLT

指令的执行不影响任何标志位。

4 、封锁数据指令 LOCK(Lock Bus Instruction)

该指令是一个前缀指令形式,在其后面跟一个具体的操作指令。LOCK 指令可以保证是 在其后指令执行过程中,禁止协处理器修改数据总线上的数据,起到独占总线的作用。该指 令的执行不影响任何标志位。

指令的格式:LOCK INSTRUCTION

相关推荐