1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 汇编语言程序设计钱晓捷第五版期末复习参考

汇编语言程序设计钱晓捷第五版期末复习参考

时间:2020-08-09 23:51:11

相关推荐

汇编语言程序设计钱晓捷第五版期末复习参考

汇编语言程序设计钱晓捷第五版期末复习参考

第一章:汇编语言基础知识

1.1 8086的寄存器

处理器内部需要高速存储单元,用于暂时存放程序执行过程中的代码和数据,这些存储单元被称为寄存器(Register)。

通用寄存器:在处理器中数量较多、使用频率较高,具有多种用途。例如,它们可用来存放指令需要的操作数据,可用来存放地址以便在主存或I/O接口中指定操作数据的位置。

专用寄存器:只用于特定目的。例如,8086的指令指针寄存器IP只用于记录将要执行指令的主存地址,标志寄存器保存指令执行的辅助信息。

8086的寄存器组分成8个通用寄存器(AX累加器、BX基址寄存器、CX计数器、DX数据寄存器、SI源地址寄存器、DI目的地址寄存器、BP基址指针、SP堆栈指针)、4个段寄存器(CS代码段寄存器、SS堆栈段寄存器、DS数据段寄存器、ES附加段寄存器)、1个标志寄存器(FLAGS)和1个指令指针寄存器(IP),它们均为16位。

1.2 8086的寻址方式

(1)立即数寻址方式

在立即数寻址方式下,指令中的操作数直接存放在机器码中,紧跟在操作码之后。立即数寻址方式常用来给寄存器或存储单元赋值。

MOV AL, 05H //功能:AL ← 05H,机器代码为B0 05MOV AX, 0102H //功能:AX ← 0102H,机器代码为B8 02 01

(2)寄存器寻址方式

寄存器寻址方式的操作数存放在CPU的内部寄存器REG中,可以是8位寄存器R8(AH、AL、BH、BL、CH、CL、DH、DL)或者16位寄存器R16(AX、BX、CX、DX、SI、DI、BP、SP)。另外,操作数可以存放在4个段寄存器SEG(CS、DS、SS、ES)中。

MOV AX, 1234H //目的操作数采用寄存器寻址,源操作数为立即数寻址AX ← 1234HMOV BX, AX //两个操作数均为寄存器寻址,BX ← AX

执行上述两条指令之后,结果是BX = 1234H。

(3)直接寻址方式

在直接寻址方式下,指令中直接包含了有效地址。

MOV AX, [2000H] //AX ← DS:[2000H]

该指令中给定了有效地址2000H,它不是存储器的物理地址。在默认情况下,有效地址要与数据段寄存器DS一起构成操作数所在存储单元的物理地址。在汇编语言中,用[]表示存储单元的内容。

该例指令的执行结果是将DS:[2000H]单元的内容传送至AX寄存器。

数据不仅可以存放于数据段中,也可以根据需要存放于附加段、代码段或堆栈段中,这时指令中应指明段超越前缀,例如:

MOV AX, ES:[2000H] //AX ← ES:[2000H]

(4)寄存器间接寻址方式

在这种寻址方式中,有效地址存放在寄存器中,8086中寄存器只能是基址寄存器BX或变址寄存器SI、DI中。其默认的段地址在DS段寄存器中,但可使用段超越前缀改变。例如:

MOV AX, [SI] //AX ← DS:[SI]

该指令中有效地址存放于SI寄存器中,操作数则存放在数据段主存单元中。假设SI内容设置为2000H,则该指令等同于MOV AX, [2000H]。

(5)寄存器相对寻址方式

在寄存器相对寻址方式下,有效地址是寄存器内容与有符号8位或16位位移量之和,寄存器可以是BX、BP或SI、DI。操作数的EA = BX/BP/SI/DI + 8/16位位移量。其中,BX、SI、DI寄存器默认数据段DS,BP寄存器默认堆栈段SS。当使用非默认段时,可用段超越前缀。

该指令中有效地址存放于SI寄存器中,操作数则存放在数据段主存单元中。假设SI内容设置为2000H,则该指令等同于MOV AX, [2000H]。

(5)寄存器相对寻址方式

在寄存器相对寻址方式下,有效地址是寄存器内容与有符号8位或16位位移量之和,寄存器可以是BX、BP或SI、DI。操作数的EA = BX/BP/SI/DI + 8/16位位移量。其中,BX、SI、DI寄存器默认数据段DS,BP寄存器默认堆栈段SS。当使用非默认段时,可用段超越前缀。

MOV AX, [DI + 06H] //AX ← DS:[DI + 06H]MOV AX, [BP + 06H] //AX ← SS:[BP + 06H]MOV AX, [BP] //等同于MOV AX, [BP + 0H]MOV AX, [SI + i] //i是事先定义的变量或常量MOV AX, i[SI] //等同于MOV AX, [SI + i]

(6)基址变址寻址方式

基址变址寻址方式是把一个基址寄存器(BX或BP)的内容加上变址寄存器(SI或DI)的内容构成有效地址EA。这样,操作数的EA = BX/BP + SI/DI。若基址寄存器使用BX,其默认段为数据段DS,若基址寄存器使用BP,其默认段为堆栈段SS。

MOV AX, [BX + SI] //AX ← DS:[BX + SI]MOV AX, [BP + DI] //AX ← SS:[BP + DI]MOV AX, DS:[BP + DI] //AX ← DS:[BP + DI]MOV AX, [BX][SI] //等同于MOV AX, [BX + SI]

(7)相对基址变址寻址方式

相对基址变址寻址方式也使用基址寄存器(BX/BP)和变址寄存器(SI/DI),还在指令中指定一个8位或16位的位移量,这三者之和构成操作数的有效地址EA,即EA = BX/BP + SI/DI + 8/16位位移量。

MOV AX, [BX + SI + 06H] //AX ← DS:[BX + SI + 06H]MOV AX, [BX + SI + i] //i是事先定义的变量或常量MOV AX, i[BX][SI] //等同于MOV AX, [BX + SI + i]和MOV AX, i[BX + SI]

第二章:8086的指令系统

'Intel 8086指令系统可分为6类:数据传送类指令,算术运算类指令,位操作类指令,控制转移类指令,串操作类指令,处理机控制类指令。

2.1 数据传送类指令

2.1.1 通用数据传送指令

(1)传送指令MOV

MOV DEST, SRC //DEST ← SRC

MOV指令把1字节或字的操作数从源地址SRC传送至目的地址DEST。源操作数可以是立即数、寄存器或主存单元,目的操作数可以是寄存器或主存单元,但不能是立即数。立即数传送例子:

MOV AL, 4 //AL ← 4,字节传送MOV CX, 0FFH //CX ← 00FFH,字传送MOV SI, 200H //SI ← 0200H,字传送MOV BYTE PTR[SI], 0AH //DS:[SI] ← 0AH,BYTE PTR说明是字节操作MOV WORD PTR[SI + 2], 0BH //DS:[SI + 2] ← 0BH,WORD PTR说明是字操作

在包括传送指令的绝大多数双操作数指令中(除非特别说明),目的操作数与源操作数必须类型一致,或者同为字,或者同为字节,否则为非法指令。例如:

MOV AL, 050AH //非法指令:050AH为字,而AL为字节

8086不允许立即数传送至段寄存器,例如:

MOV DS, 100H //非法指令:不允许立即数至段寄存器的传送

寄存器传送例子:

MOV AX, BXMOV AH, ALMOV DS, AXMOV [BX], AL

存储器传送例子:

MOV AL, [BX]MOV DX, [BP]MOV ES, [SI]

8086指令系统除串操作类指令外,不允许两个操作数都是存储单元,所以没有主存至主存的数据传送,要实现这种传送可通过寄存器间接实现。

例如将buffer1单元的数据传送至buffer2单元,buffer1和buffer2是两个字变量:

MOV AX, buffer1MOV buffer2, AX

不能向CS段传送数据,因为改变CS值将导致程序执行混乱

MOV CS, [SI] //非法指令

段寄存器传送例子:

MOV [SI], DSMOV AX, ESMOV DS, AX

不允许段寄存器之间的直接数据传送,例如:

MOV DS, ES //非法指令:不允许seg ← seg传送

(2)交换指令XCHG

交换指令用来将源操作数和目的操作数内容交换,例如:

MOV AX, 1234H //AX = 1234HMOV BX, 5678H //BX = 5678HXCHG AX, BX //AX = 5678H, BX = 1234HXCHG AH, AL //AX = 7856HXCHG AX, [2000H] //等同于XCHG [2000H], AXXCHG AL, [2000H] //等同于XCHG [2000H], AL

(3)换码指令XLAT

换码指令用于将BX指定的缓冲区中,AL指定的位移处的数据取出赋值给AL,即AL ← DS:[BX + AL]。

例如将首地址为100H的表格缓冲区的3号数据取出:

MOV BX, 100HMOV AL, 03HXLAT

2.1.2 堆栈操作指令

(1)进栈指令PUSH

进栈指令先使堆栈指针SP减2,然后把一个字操作数存入堆栈顶部。堆栈操作的对象只能是字操作数,进栈时,低字节存放于低地址,高字节存放在高地址,SP相应向低地址移动2字节单元。

例如将7812H压入堆栈:

MOV AX, 7812HPUSH AX

将主存单元DS:[2000H]的一个字压入堆栈:

PUSH [2000H]

(2)出栈指令POP

出栈指令把栈顶的一个字传送至指定的目的操作数,然后堆栈指针SP加2。目的操作数应为字操作数,字从栈顶弹出时,低地址字节送低字节,高地址字节送高字节。

例如将栈顶的一个字的内容弹出送入AX寄存器:

POP AX

将栈顶一个字送入主存DS:[2000H]

POP [2000H]

2.1.3 标志传送指令

(1)标志寄存器传送

标志寄存器传送指令用来传送标志寄存器的内容,包括LAHF/SAHF、PUSHF/POPF指令。

①标志送AH指令LAHF

LAHF指令将标志寄存器FLAGS的低字节送寄存器AH,即状态标志位SF/ZF/AF/PF/CF分别送入AH的第7/6/4/2/0位,而AH的第5/3/1位任意。

LAHF //AH ← FLAGS的低字节

②AH送标志指令SAHF

SAHF将AH寄存器内容送FLAGS的低字节,即SAHF和LAHF是一对功能相反的指令,它们只影响标志寄存器的低8位,而对高8位无影响。

SAHF //FLAGS的低字节 ← AH

③标志进栈指令PUSHF

PUSHF指令将标志寄存器的内容压入堆栈,同时栈顶指针SP减2。这条指令可用来保存全部标志位。

PUSHF

④标志出栈指令POPF

POPF指令将栈顶字单元内容送标志寄存器,同时栈顶指针SP加2.

POPF

(2)标志位操作

标志位操作指令可用来对CF、DF和IF三个标志位进行设置,除影响其所设置的标志外,均不影响其他标志。

CLC //复位进位标志:CF ← 0STC //置位进位标志:CF ← 1CMC //求反进位标志:CF ← ~CFCLD //复位方向标志:DF ← 0STD //置位方向标志:DF ← 1CLI //复位中断标志:IF ← 0STI //置位中断标志:IF ← 1

2.1.4 地址传送指令

(1)有效地址传送指令LEA

LEA指令将存储器操作数的有效地址传送至指定寄存器。

MOV BX, 0400HMOV SI, 3CHLEA BX, [BX + SI + 0F62H] //BX ← BX + SI + 0F62H = 0040H + 3CH + 0F62H = 139EH

这里,BX得到的是主存单元的有效地址,不是物理地址,也不是该单元的内容。

(2)指针传送指令

LDS和LES指令将主存中MEM指定的字送至R16,并将MEM的下一字送DS或ES寄存器。实际上,MEM指定了主存的连续4字节作为逻辑地址,即32位的地址指针。

MOV WORD PTR [3060H], 0100HMOV WORD PTR [3062H], 1450HLDS SI, [3060H] //DS = 1450H, SI = 0100HLES DI, [3060H] //ES = 1450H, DI = 0100H

2.2 算术运算类指令

2.2.1 状态标志

CF(进位标志位):当执行一个加法(减法)运算时,最高位产生进位(或借位)时,CF为1,否则为0。

ZF(零标志位):若当前的运算结果为零,则ZF为1,否则为0。

SF(符号标志位):该标志位与运算结果的最高位相同。即运算结果为负,则SF为1,否则为0。

OF(溢出标志位):若运算结果超出机器能够表示的范围称为溢出,此时OF为1,否则为0。判断是否溢出的方法是:进行二进制运算时,最高位的进位值与次高位的进位值进行异或运算,若运算结果为1则表示溢出OF=1,否则OF=0

PF(奇偶标志位):当运算结果的最低16位中含1的个数为偶数则PF=1否则PF=0

AF(辅助进位标志):一个加法(减法)运算结果的低4位向高4位有进位(或借位)时则AF=1否则AF=0

另外还有三个控制标志位用来控制CPU的操作,可以由程序进行置位和复位。

TF(跟踪标志位):该标志位为方面程序调试而设置。若TF=1,8086/8088CPU处于单步工作方式,即在每条指令执行结束后,产生中断。

IF(中断标志位):该标志位用来控制CPU是否响应可屏蔽中断。若IF=1则允许中断,否则禁止中断。

DF(方向标志位):该标志位用来控制串处理指令的处理方向。若DF=1则串处理过程中地址自动递减,否则自动递增。

2.2.2 加法指令

加法指令包括ADD、ADC和INC指令,执行字或字节的加法运算。

(1)加法指令ADD

加法指令ADD将源操作数与目的操作数相加,结果送到目的操作数,支持寄存器与立即数、寄存器、存储单元,以及存储单元与立即数、寄存器间的加法运算。

MOV AL, 0FBH //AL = 0FBHADD AL, 07H //AL = 02HMOV WORD PTR [200H], 4652H //[200H] = 4652HMOV BX, 1FEH //BX = 1FEHADD AL, BL //AL = 00HADD WORD PTR [BX + 2], 0F0F0H //[200H] = 3742H

(2)带进位加法指令ADC

ADC指令除完成ADD加法运算外,还要加进位CF,其用法及对状态标志的影响也与ADD指令一样。ADC指令主要用于与ADD指令相结合实现多精度数相加。

MOV AX, 4652H //AX = 4652HADD AX, 0F0F0H //AX = 3742H, CF = 1MOV DX, 0234H //DX = 0234HADC DX, 0F0F0H //DX = 0F352H, CF = 0

(3)增量指令INC

INC指令对操作数加1(增量),是一个单操作数指令,操作数可以是寄存器或存储器。

INC BXINC BYTE PTR [BX]

2.2.3 减法指令

减法指令包括SUB、SBB、DEC、NEG和CMP,执行字或字节的减法运算,除DEC不影响CF标志外,其他减法指令按定义影响全部状态标志位。

(1)减法指令SUB

减法指令SUB使目的操作数减去源操作数,结果送目的操作数,支持的操作数类型同加法指令。

MOV AL, 0FBH //AL = 0FBHSUB AL, 07H //AL = 0F4H, CF = 0MOV WORD PTR[200H], 4652H //[200H] = 4652HMOV BX, 1FEH //BX = 1FEHSUB AL, BL //AL = 0F6H, CF = 1SUB WORD PTR[BX + 2], 0F0F0H //[200H] = 5562H, CF = 1

(2)带借位减法指令SBB

带借位减法指令SBB使目的操作数减去源操作数,还要减去借(进)位CF,结果送到目的操作数。SBB指令主要用于与SUB指令相结合,实现多精度数相减。

MOV AX, 4652H //AX = 4652HSUB AX, 0F0F0H //AX = 5562H, CF = 1MOV DX = 0234H //DX = 0234HSBB DX, 0F0F0H //DX = 1143H, CF = 1

(3)减量指令DEC

DEC指令对操作数减1(减量),是一个单操作数指令,操作数可以是寄存器或存储器。

DEC CXDEC WORD PTR [SI]

INC与DEC指令不影响进位CF标志,但影响其他状态标志。

(4)求补指令NEG

NEG指令也是一个单操作数指令,对操作数执行求补运算,即用零减去操作数(将操作数按位取反后加一),然后将结果返回操作数。

MOV AX, 0FF64H //AX = 0FF64HNEG AL //AX = 0FF9CH, SF = 1, PF = 1, CF = 1SUB AL, 9DH //AX = 0FFFFH, SF = 1, PF = 1, CF = 1NEG AX //AX = 0001H, SF = 0, PF = 0, CF = 1DEC AL //AX = 0000H, SF = 0, ZF = 1, PF = 1, CF = 1NEG AX //AX = 0000H, SF = 0, ZF = 1, PF = 1, CF = 0

(5)比较指令CMP

比较指令将目的操作数减去源操作数,但结果不回送目的操作数。也就是说,CMP指令与减法指令SUB执行同样的操作,同样影响标志,只是不改变目的操作数。

例如比较AL是否大于100:

CMP AL, 100 //AL - 100JB below //若AL < 100,则跳转到below执行SUB AL, 100 //若AL >= 100,则AL ← AL - 100INC AH //AH ← AH + 1below: ...

2.2.4 乘法指令

乘法指令用来实现两个二进制操作数的相乘运算,包括两条指令:无符号数乘法指令MUL和有符号数乘法指令IMUL。乘法指令隐含使用一个操作数AX和DX,源操作数则显式给出。如果是字节量相乘,则AL与R8/M8相乘得到16位的字,存入AX中;如果是字相乘,则AX与R16/M16相乘得到32位的结果,其高字存入DX,低字存入AX。

无符号数0B4H与11H相乘:

MOV AL, 0B4H //AL = 0B4H = 180DMOV BL, 11H //BL = 11H = 17DMUL BL //AX = 0BF4H = 3060D, OF = CF = 1(AX高8位不为0)

有符号数0B4H与11H相乘:

MOV AL, 0B4H //AL = 0B4H = -76DMOV BL, 11H //BL = 11H = 17DIMUL BL //AX = 0FAF4H = -1292D, OF = CF = 1

2.2.5 除法指令

除法指令执行两个二进制数的除法运算,包括无符号二进制数除法指令DIV和有符号二进制数除法指令IDIV两条指令。除法指令隐含使用DX和AX作为一个操作数,指令中给出的源操作数是除数。如果是字节除法,AX除以R8/M8,8位商存入AL,8位余数存入AH;如果是字除法,DX.AX除以R16/M16,16位商存入AX,16位余数存入DX。

无符号数0400H除以B4H:

MOV AX, 0400H //AX = 400H = 1024DMOV BL, 0B4H //BL = 0B4H = 180DDIV BL //商AL = 05H,余数AH = 7CH = 124D

有符号数0400H除以B4H:

MOV AX, 0400H //AX = 400H = 1024DMOV BL, 0B4H //BL = 0B4H = -76DIDIV BL //商AL = 0F3H = -13D,余数AH = 24H = 36D

2.2.6 符号扩展指令

8086设计有两条符号扩展指令CBW和CWD。CBW指令将AL的最高有效位D7 扩展至AH,即:如果AL的最高有效位是0,则AH = 00;AL的最高有效位为1,则AH = FFH,AL不变。CWD将AX的内容符号扩展形成DX,即:如果AX的最高有效位D15为0,则DX = 0000H;如果AX的最高有效位D15 为1,则DX = FFFFH。

MOV AL, 80H //AL = 80HCBW //AX = 0FF80HADD AL, 255 //AL = 7FHCBW //AX = 007FH

2.3 位操作类指令

2.3.1 逻辑运算指令

逻辑运算指令用来对字或字节按位进行逻辑运算,包括5条指令:逻辑与AND、逻辑或OR、逻辑非NOT、逻辑异或XOR和测试TEST。

(1)逻辑与指令AND

AND指令对两个操作数执行按位的逻辑与运算,结果送至目的操作数。在这两个操作数中,源操作数可以是任意寻址方式,目的操作数只能是立即数之外的其他寻址方式,且两个操作数不能同时为存储器寻址方式。

MOV AL, 45HAND AL, 31H //AL = 01H, CF = OF = 0, SF = 0, ZF = 0, PF = 0

AND指令可用于复位某些位,不影响其他位,例如将BL中D0和D3 清零,其余位不变,则:

AND BL, 11110110B

(2)逻辑或指令OR

OR指令对两个操作数执行按位的逻辑或运算,结果送至目的操作数,所支持的操作数同AND指令。

MOV AL, 45HOR AL, 31H //AL = 75H, CF = OF = 0, SF = 0, ZF = 0, PF = 0

OR指令可置位某些位,不影响其他位,例如将BL中D0和D3置1,其余位不变,则:

OR BL, 00001001B

(3)逻辑异或指令XOR

XOR指令对两个操作数执行按位的逻辑异或运算,结果送至目的操作数,所支持的操作数同AND指令。

MOV AL, 45HXOR AL, 31H //AL = 74H, CF = OF = 0, SF = 0, ZF = 0, PF = 1

XOR可用于求反某些位或将寄存器清零:

XOR BL, 00001001B //将BL的第0和3位求反XOR AX, AX //AX = 0, CF = OF = 0, SF = 0, ZF = 1, PF = 1

(4)逻辑非指令NOT

NOT指令对操作数按位取反,NOT指令是一个单操作数指令,该操作数可以是立即数之外的任何寻址方式,NOT指令不影响标志位。

MOV AL, 45HNOT AL //AL = 0BAH

(5)测试指令TEST

TEST指令对两个操作数执行按位的逻辑与运算,但结果不返回至目的操作数,只根据结果来设置状态标志。TEST指令通常用于检测一些条件是否满足但又不希望改变原操作数的情况,这条指令之后一般是条件转移指令,目的是利用测试条件转向不同的程序段。

TEST AL, 01H //测试AL的最低位是否为1JNZ there //如果最低位为1,则ZF = 0,程序转移到there... //否则最低位为0,则ZF = 1,顺序执行there: ...2.3.2 移位指令

移位指令分成逻辑移位指令和算术移位指令,分别具有左移或右移操作。

SHL reg/mem, 1/CL //逻辑左移:reg/mem左移1/CL位,最低位补0,最高位进入CFSHR reg/mem, 1/CL //逻辑右移:reg/mem右移1/CL位,最高位补0,最低位进入CFSAL reg/mem, 1/CL //算术左移,功能与SHL相同SAR reg/mem, 1/CL //算术右移:reg/mem右移1/CL位,最高位不变,最低位进入CF

移位指令的目的操作数可以是寄存器或存储单元。源操作数表示移位位数,当移位位数大于1时,需要用CL寄存器的值来表示。移位指令按照移入的位设置进位标志CF,如果进行1位移动,则按照操作数的最高符号位是否改变,相应设置溢出标志OF:如果移位前的操作数最高位与移位后操作数的最高位不同(有变化),则OF = 1,否则OF = 0。当移位次数大于1时,OF不确定。

MOV CL, 4MOV AL, 0F0H //AL = 0F0HSHL AL, 1 //AL = E0H, CF = 1, SF = 1, ZF = 0, PF = 0, OF = 0SHR AL, 1 //AL = 70H, CF = 0, SF = 0, ZF = 0, PF = 0, OF = 1SAR AL, 1 //AL = 38H, CF = 0, SF = 0, ZF = 0, PF = 0, OF = 0SAR AL, CL //AL = 03H, CF = 1, SF = 0, ZF = 0, PF = 1

2.3.3 循环移位指令

循环移位指令类似移位指令,但要从一端移出的位返回到另一端形成循环,分为不带进位循环移位和带进位循环移位,分别具有左移或右移操作。

ROL reg/mem, 1/CL //不带进位循环左移ROR reg/mem, 1/CL //不带进位循环右移RCL reg/mem, 1/CL //带进位循环左移RCR reg/mem, 1/CL //带进位循环右移

前两条指令不将进位CF纳入循环位中。后两条指令将进位标志CF纳入循环为中,与操作数一起构成的9位或17位二进制数一起移位。

循环移位指令的操作数形式与移位指令相同,如果仅移动1次,可以用1表示;如果移位多次,则需用CL寄存器表示移位次数。循环移位指令按照指令功能设置进位标志CF,不影响SF、ZF、PF、AF标志。对OF标志的影响,循环移位指令与前面介绍的移位指令一样。

例如把AL最低位送BL最低位,但保持AL不变:

ROR BL, 1ROR AL, 1RCL BL, 1ROL AL, 1

2.4 控制转移类指令

控制转移类指令通过修改CS和IP寄存器的值来改变程序的执行顺序,包括5组指令:无条件转移指令、有条件转移指令、循环指令、子程序指令和中断指令。

2.4.1 无条件转移指令

无条件转移就是无任何先决条件就能使程序改变执行顺序。处理器只要执行无条件转移指令JMP,就使程序转到指令的目标地址处,从目标地址处开始执行那里的指令。

JMP指令可以将程序转移到1MB存储空间的任何位置。根据跳转的距离,JMP指令分为段内转移和段间转移。

段内转移是指在当前代码段64KB范围内转移,因此不需要更改CS段地址,只要改变IP偏移地址。如果转移范围可以用一个8位数(-128~+127之间的位移量)表达,则可以形成“短地址”(short jump);如果地址用一个16位数表达,则形成“近转移”(near jump),± 32 \pm32±32KB范围内。

段间转移是指从当前代码段跳转到另一个代码段,此时需要更改CS段地址和IP偏移地址,这种转移也称为“远转移”(far jump)。转移的目标地址必须用一个32位数表达,叫做32位远指针,它就是逻辑地址。

(1)段内转移,相对寻址

JMP label //IP ← IP + 位移量

(2)段内转移,间接寻址

JMP r16/m16 //IP ← r16/m16

这种形式的JMP指令,将一个16位寄存器或主存单元内容送入IP寄存器,作为新的指令指针,但不修改CS寄存器的内容。例如:

JMP AX //IP ← AXJMP WORD PTR[2000H] //IP ← [2000H]

(3)段间转移,直接寻址

段间直接转移指令是将标号所在段的段地址作为新的CS值,标号在该段内的偏移地址作为新的IP值。这样,程序就能跳转到新的代码段执行。

JMP FAR PTR label //IP ← label的偏移地址,CS ← label的段地址

(4)段间转移,间接寻址

JMP FAR PTR mem //IP ← [mem],CS ← [mem + 2]

段间间接转移指令用一个双字存储单元表示要跳转的目标地址。这个目标地址存放在主存中连续的两个字单元中,其中低位字送IP寄存器,高位字送CS寄存器。例如:

MOV WORD PTR[BX], 0MOV WORD PTR[BX + 2], 1500HJMP FAR PTR[BX] //转移到1500H : 0

2.4.2 条件转移指令

条件转移指令中的条件如下表所示:

(1)判断单个标志位状态

①JZ/JE和JNZ/JNE利用零标志ZF,判断结果是否为零(或相等)。

例:如果AL最高位为0,则设置AH=0;如果AL最高位为1,则设置AH=FFH(也就是用一段程序实现符号扩展指令CBW的功能)。

TEST AL, 80H //测试最高位JZ next0 //最高位为0(ZF = 1),转移到next0MOV AH, 0FFH //最高位为1,顺序执行JMP done //无条件转向donenext0: MOV AH, 0done: ...

②JS和JNS利用符号标志SF,判断结果是正是负。

例:计算|X-Y|,X和Y为存放于X单元和Y单元的16位操作数,结果存入RESULT中。

②JS和JNS利用符号标志SF,判断结果是正是负。

例:计算|X-Y|,X和Y为存放于X单元和Y单元的16位操作数,结果存入RESULT中。

MOV AX, XSUB AX, Y //AX ← X - Y,下面求绝对值JNS nonneg //为正数,不需处理,直接转向保存结果NEG AX //为负数,进行求补,得到绝对值nonneg: MOV RESULT, AX

③JO和JNO利用溢出标志OF,判断结果是否产生溢出。

例:计算X-Y,X和Y分别为存放于X单元和Y单元中的16位有符号操作数。若溢出,则转移到

OVERFLOW处理。MOV AX, XSUB AX, YJO overflow... //没有溢出,结果正确overflow: ... //溢出处理

④JP/JPE和JNP/JPO利用奇偶标志PF,判断结果中“1”的个数是偶数还是奇数。

例:设字符的ASCII编码在AL寄存器中,将字符加上奇校验位。

AND AL, 7FH //最高位置0,同时判断1的个数JNP NEXT //个数已为奇数,则转向nextOR AL, 80H //否则,最高位置1next: ...

⑤JC/JB/JNAE和JNC/JNB/JAE,利用进位标志CF,判断结果是否进位或借位。

例:记录BX中1的个数。

XOR AL, ALagain:TEST BX, 0FFFFH //等价于CMP BX, 0JE nextSHL BX, 1JNC againINC ALJMP again...next: ... //AL保存1的个数

(2)用于比较无符号数高低

例:比较无符号数的大小,将较大的存入RESULT主存单元。

CMP AX, BX //比较AX和BXJNB next //若AX ≥ BX,转移到nextXCHG AX, BX //若AX < BX,交换next: MOV RESULT, AX(3)用于比较有符号数大小

例:比较有符号数大小,将较大的存入RESULT主存单元。

CMP AX, BX //比较AX和BXJNL next //若AX ≥ BX,转移到nextXCHG AX, BX //若AX < BX,交换next: MOV RESULT, AX

2.4.3 循环指令

JCXZ label //CX = 0,则转移,否则顺序执行LOOP label //CX ← CX - 1,若CX ≠ 0,循环:IP ← IP + 位移量,否则顺序执行LOOPZ/LOOPE label //CX ← CX - 1,若CX ≠ 0且ZF = 1,循环:IP ← IP + 位移量,否则顺序执行LOOPNZ/LOOPNE label //CX ← CX - 1,若CX ≠ 0且ZF = 0,循环:IP ← IP + 位移量,否则顺序执行

JCXZ指令在CX寄存器为0时退出循环;

LOOP指令首先将计数值CX减一,然后判断计数值CX是否为0。CX不为0则继续执行循环体内的指令;CX为0表示循环结束。LOOPZ和LOOPNZ指令中要求同时ZF为1或0才进行循环,用于判断结果是否为0或相等,以便提前结束循环。

JCXZ指令在CX寄存器为0时退出循环;

LOOP指令首先将计数值CX减一,然后判断计数值CX是否为0。CX不为0则继续执行循环体内的指令;CX为0表示循环结束。LOOPZ和LOOPNZ指令中要求同时ZF为1或0才进行循环,用于判断结果是否为0或相等,以便提前结束循环。

例:记录附加段中STRING字符串包含空格字符的个数。假设字符串长度为COUNT字节,结果存入RESULT单元。

MOV CX, COUNT //设置循环次数MOV SI, OFFSET stringXOR BX, BX //BX清零,用于记录空格数JCXZ done //如果长度为0则退出MOV AL, 20Hagain:CMP AL, ES : [SI]JNZ next //ZF = 0,不是空格,转移INC BX //ZF = 1,有空格,空格个数加一next:INC SILOOP again //字符个数减一,不为零则继续循环done:MOV RESULT, BX //保存结果

2.4.4 子程序指令

子程序由主程序执行子程序调用指令CALL来调用;而子程序执行完后用子程序返回指令RET,返回主程序继续执行。CALL和RET指令均不影响标志位。

2.4.4 子程序指令

子程序由主程序执行子程序调用指令CALL来调用;而子程序执行完后用子程序返回指令RET,返回主程序继续执行。CALL和RET指令均不影响标志位。

例:利用子程序完成将AL低4位中的1位十六进制数转换成对应的ASCII码。

//主程序MOV AL, 0FH //提供参数ALCALL htoasc //调用子程序...htoasc: //子程序AND AL, 0FH //只取AL的低四位OR AL, 30H //AL高四位变成3CMP AL, 39H //判断是0~9还是a~fJBE htoendADD AL, 7 //若为a~f,其ASCII还要加上7htoend: ret //子程序返回

第三章:汇编语言程序格式

3.1 汇编语言程序的开发

3.1.1 汇编语言程序的语句格式

(1)标号与名字

执行性语句中,:前的标号表示处理器指令在主存中的逻辑地址,主要用于指示分支、循环等程序的目的地址,可有可无。说明性语句中的名字可以是变量名、段名、子程序名等,反映变量、段和子程序等的逻辑地址。标号采用:分隔处理器指令,名字采用空格或制表符分隔伪指令,据此也分开了两种语句。

(2)助记符

助记符是帮助记忆指令的符号,反映指令的功能。处理器指令助记符可以是任何一条指令,表示一种处理器操作。例如,程序中使用最多的数据传送指令,其助记符是MOV。

(3)操作数和参数

处理器指令的操作数表示参与操作的对象,可以是一个具体的常量,也可以是保存在寄存器的数据,还可以是一个保存在存储器中的变量。在双操作数的指令中,目的操作数写在,前,还用来存放指令操作的结果;对应地,,后的操作数就称为源操作数。

(4)注释

语句中;后的内容是注释,通常是对指令或程序片段功能的说明,是为了程序便于阅读而加上的,不是必须有的。必要时,一个语句行也可以由;开始作为阶段性注释。

3.1.2 汇编语言的源程序框架

(1)简化段定义的源程序框架

MASM各版本支持多种汇编语言源程序格式。MASM 6.x版本的简化段定义典型格式如下:

.model small //定义程序的存储模式(small表示小型模式).stack //定义堆栈段(默认是1KB空间).data //定义数据段... //数据定义.code //定义代码段.startup //程序起始点,并设置DS和SS内容... //主程序代码.exit 0 //程序终止点,返回DOS(0是返回值)... //子程序代码end //汇编结束

在简化段定义的源程序格式中,以.开始的伪指令说明程序的结构。首先,必须具有存储模型伪指令.MODEL,随后,.STACK、.DATA和.CODE依次定义堆栈段、数据段和代码段,一个段的开始自动结束上一个段。

例如:显示“Hello Everybody!”,采用简化段定义的源程序框架如下:

.MODEL SMALL.STACK.DATAstring DB 'Hello, Everybody!', 0DH, 0AH, '$'.CODE.STARTUPMOV DX, OFFSET stringMOV AH, 9INT 21H.EXIT 0END

(2)完整段定义的源程序框架

上文中的程序完整段定义的源程序如下:

STACK SEGMENTDB 1024 DUP(?)STACK ENDSDATA SEGMENTstring DB 'Hello, Everybody!', 0DH, 0AH, '$'DATA ENDSCODE SEGMENTASSUME CS: CODE, DS: DATA, SS: STACKSTART:MOV AX, DATAMOV DS, AXMOV DX, OFFSET stringMOV AH, 9INT 21HMOV AX, 4C00HINT 21HCODE ENDSEND START

3.1.3 汇编语言程序的开发过程

3.1.4 DOS系统功能的调用

调用DOS操作系统功能的一般方法如下:

(1)在AH寄存器中设置系统功能调用号,说明选择的功能;

(2)在指定寄存器中设置入口参数,以便按照要求执行功能;

(3)用中断调用指令INT 21H执行功能调用;

(4)根据出口参数分析功能调用执行情况。

下表列出了主要使用的基本DOS功能调用:

(1)字符输出

使用02H号DOS系统功能调用在显示器输出一个字符:

MOV AH, 02H //设置功能号:AH ← 02HMOV DL, '?' //提供入口参数:DL ← '?'INT 21H //DOS功能调用:显示

(2)字符串输出

使用09H号DOS功能要事先将欲显示的字符串保存在主存,设置入口参数DS:DX等于该字符串在主存中的首地址,注意字符串必须以’$’(24H)结束,可以输出回车(0DH)和换行(0AH)字符产生回车和换行的作用。

string DB 'Hello, Everybody!', 0DH, 0AH, '$' //在数据段定义要显示的字符串MOV AH, 09H //设置功能号:AH ← 09HMOV DX, OFFSET string //提供入口参数:DX ← 字符串的偏移地址INT 21H //DOS功能调用:显示

(3)字符输入

调用01H号DOS功能时,若无键按下,则会一直等待,直到按键后才读取该键值,并使用AL保存出口参数,即输入字符的ASCII编码。例如:判断按键是Y还是N(大写)。

getkey:MOV AH, 1 //设置功能号:AH ← 01HINT 21H //DOS功能调用:等待按键CMP AL, 'Y' //分析出口参数是否为YJE yeskeyCMP AL, 'N' //分析出口参数是否为NJE nokeyJNE getkey //不是Y或N,继续输入

(4)字符串输入

用0AH号DOS系统功能调用从键盘输入一个字符串:

buffer //定义缓冲区DB 81 //第1字节填入可能输入的最大字符数DB 0 //第2字节将用于存放实际输入的字符数DB 81 DUP(0) //第3字节开始用于存放输入的字符串...MOV AH, 0AHMOV DX, SEG bufferMOV DS, DXMOV DX, OFFSET bufferINT 21H

(5)按键判断

例如:按任意键继续的程序片段:

... //提示“按任意键继续”getkey:MOV AH, 0BH //设置功能号:AH ← 0BHINT 21H //DOS功能调用:判断按键否OR AL, AL //分析出口参数:AL = 0 ?JZ getkey //AL = 0,没有按键,继续等待

3.2 参数、变量和标号

3.2.1 数值型参数

3.2.2 变量定义伪指令

变量定义伪指令为变量申请固定长度的存储空间,并可以同时将相应的存储单元初始化,其汇编格式为变量名 伪指令 初值表。

(1)变量名为用户自定义标识符,表示初值表首元素的逻辑地址,即用这个符号表示地址,常称为符号地址。变量名可以没有,在这种情况下,汇编程序将直接为初值表分配空间,无符号地址。

(2)初值表是用,分隔的参数,主要由数值常数、表达式或?、DUP组成。其中?表示初值不确定,即未赋初值;重复初值可以用DUP进行定义。DUP的格式为:重复次数 DUP(重复参数)

(3)变量定义伪指令有DB、DW、DD、DF、DQ、DT,它们根据申请的主存空间单位分类,下面逐一介绍。

(1)定义字节单元伪指令

字节定义伪指令DB,用于分配1字节或多字节单元,并可以将它们初始化为指定值。

.DATAX DB 'a', -5DB 2DUP(100), ?Y DB 'ABC'

利用这些变量的汇编指令示例如下:

MOV AL, X //此处X表示它的第一个数据,故AL ← 'a'DEC X + 1 //对X为起始的第二个数据减一,故成为-6MOV Y, AL //现在Y这个字符串成为'aBC'

(2)定义字单元伪指令

一个字单元可用于存放任何16位数据。

.DATACOUNT DW 8000H, ?, 'ab'MAXINT EQU 64HNUMBER DW MAXINTARRAY DW MAXINT DUP(0)

(3)定义双字单元伪指令

一个双字单元可用于存放任何32位数据。

VARDD DD 0, ?, 12345678HFARPOINT DD 00400078H

(4)其他数据定义伪指令

DF:定义3字伪指令;DQ:定义4字伪指令;DT:定义10字节伪指令。

例:定义一个缓冲区,包含33H、34H、35H和36H四个字节字符,把这四个数据依次复制20次,存入接着的存储区,最后显示出复制结果。

//数据段source DB 33H, 34H, 35H, 36Htarget DB 80 DUP(?)//代码段MOV SI, OFFSET SOURCEMOV DI, OFFSET TARGETMOV CX, 80again:

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。