格数据或一维数组中的任意元素。
例见P.102例3-8。
需要特别指出的是在汇编语言中,相对寻址的书写格式有几种不同的形式,例见P.103。 注意:在有些教科书中,也有将使用BX或BP作为间址寄存器的寄存器相对寻址称为基址寻址;而将用SI、DI作为间址寄存器的寄存器相对寻址称为变址寻址。
3.2.6 基址—变址寻址
在基址—变址寻址方式中,偏移地址由一个基址寄存器(BX、BP)的内容和一个变址寄存器(SI、DI)的内容相加而形成,称为基址—变址寻址。在默认情况下,指令中如用BX作基址寄存器,则段地址在DX中,如用BP作基址寄存器,则段地址在SS中。同样,也可允许段超越。
例见P.103例3-9。
使用基址—变址寻址方式时,不允许同时使用两个基址寄存器或两个变址寄存器。
3.2.7 基址—变址—相对寻址
基址—变址—相对寻址是基址—变址寻址的扩充。指令中指定一个基址寄存器,一个变址寄存器,同时还给出一个8位或16位的位移量,将三者相加得到操作数的偏移地址。默认的段寄存器,仍取决于使用的基址寄存器,也允许段超越。
例见P.104例3-10。 使用该寻址方法可方便地访问二维数组。利用基址寄存器存放数组的首址,而变址寄存器和位移量分别确定行和列的值,则可寻访二维数组中的指定行和列的元素。
与寄存器相对寻址类似,基址—变址—相对寻址指令也可用多种表达形式,例见P.104。 同样,基址—变址—相对寻址也不允许同时使用两个基址寄存器或两个变址寄存器。
3.2.8 隐含寻址
有些指令的操作不仅指明了进行何种操作,还隐含了部分操作数的地址。如乘除指令,指令中只给出乘数(或除数)的地址,而被乘数(或被除数)的地址是隐含(且固定)的。这种将一个操作数隐含在指令码中的寻址方式称为隐含寻址。
例见P.105例3-11。
3.3 8086指令系统
在讨论各种指令的特点、用途和功能,先介绍本节所用到的各种符号: OPRD 泛指各种类型操作数 Mem 存储器操作数 acc 累加器操作数 dest 目标操作数 src 源操作数
disp 8位或16位偏移量(可用符号地址表示) DATA 8位或16位立即数
port 输入输出端口(可用数字或表达式表示) ( ) 表示寄存器的内容 [ ] 表示存储器的内容
26
3.3.1 数据传送类指令
数据传送类指令是程序中使用频度最高的一类指令。数据传送类指令绝大多数不会对标志寄存器FLAGS产生影响。
数据传送类指令按功能又可分为4小类:
·通用数据传送指令 ·目标地址传送指令 ·标志传送指令 ·输入输出指令 1.通用数据传送指令
通用数据传送指令由包括一般传送指令MOV、堆栈操作指令PUSH和POP、交换指令XCHG、查表指令XLAT及字位扩展指令,下分别介绍:
1)一般传送指令MOV(move) 指令格式及操作功能
MOV dest,src ;(dest)←(src)
指令中dest表示目标操作数,src表示源操作数,指令功能是将一个操作数由源地址送到目标地址,而源地址中的操作数保持不变。
注意:在汇编语言中,规定凡具有双操作数的指令,目标操作数写在前面,源操作数写在后面,两者之间用一个逗号隔开。
MOV指令有以下特点:
·既可一次传送一个字节操作数(8位),也可一次传送一个字操作数(16位),具体取决于指令中涉及的寄存器或立即数的位数。 ·可用上节讲过的各种寻址方式。 ·可实现下述各种传送:
(1)寄存器与寄存器之间的数据传送
16位数据的传送指令,例如: MOV BX,SI ;变址寄存器SI中的内容送到基址寄存器BX MOV DS,AX ;累加器AX的内容送到段寄存器DS MOV AX,CS ;段寄存器CS的内容送到累加器AX 8位数据的传送指令,例如: MOV MOV
AL,CL DL,CH
;通用寄存器CL中的内容送AL ;通用寄存器CH中的内容送DL
如(CX)= 2233H,上两条指令执行后(AL)= 33H,(DL)= 22H (2)寄存器与存储器之间的传送
可以是8位数据传送,也可以是16位数据传送,可以是寄存器到存储器的传送,也可以是存储器到寄存器的传送。例如:
MOV
CL,[BP][DI]
;SS段偏移地址为(BP)+(DI)的存储单元内容送CL。
如(SS)= 8000H, (BP)= 1020H,(DI)= 0383H,(813A3H)= 44H,则上指令执行后,
(CL)= 44H。
当传送16位数据(字操作数)时,这时对连续两个存储器单元进行存取,且寄存器的低8位对应存储器的低地址单元,寄存器的高8位对应存储器的高地址单元,例如: MOV [BX],AX ;将AX的内容送连续两个存储器单元 如(DS)= 6000H,(BX)= 1200H,(AX)= 1234H,则上指令执行后,(61200H)= 34H,(61201H)= 12H。
27
(3)立即数到寄存器的传送
MOV AL,5 ;将立即数05H送累加器AL MOV BX,3078H ;将立即数3078H送寄存器BX (4)立即数到存储器的传送
MOV BYTE PTR[BP+SI],5 ;将立即数05H送到SS段偏移量为(BP)+(SI)的单
MOV
;元中
WORD PTR[BX],1005H ;将立即数1005H分送DS段偏移地址为(BX)和
;(BX)+ 1的两个存储单元 (5)存储器与段寄存器之间的传送 MOV
DS,[1000H] [BX],ES
;将DS段偏移地址为1000H和1001H的两个存储单元的 ;内容送段寄存器DS
;将段寄存器ES的内容分送DS段偏移地址为(BX)和
MOV
;(BX)+ 1的两个存储单元 如上两指令执行前(DS)= 8000H,(ES)= 4000H,(BX)= 1200H,(81000H)= 00H,
(81001H)= 20H,执行后(DS)= 2000H,(21200H)= 00H,(21201H)= 40H。 用MOV指令进行数据传送必须注意以下几点:
①MOV指令的两个操作数类型必须相同。 下列指令为错误指令: MOV AX,BL
②不能两个操作数同为存储器操作数。 下列指令为错误指令:
MOV [BX],[SI]
③不能用立即数给段寄存器赋值(需通过两条指令) 下列指令为错误指令: MOV DS,1234H
④不能在段寄存器间直接传送数据(需通过两条指令) 下列指令为错误指令:
MOV DS,ES
⑤一般情况下,IP和CS的内容不能通过MOV指令修改。IP、CS不能作目标操作数,只能作源操作数。
⑥FLAGS内容不能通过MOV指令作修改。 MOV传送指令举例:
例:把内存中首地址为MEM1的200个字节的数据送到首地址为MEM2的区域中。 解:程序如下(部分指令尚未学到):
MOV MOV MOV
SI,OFFSET MEM1 ;源数据块首地址(偏移地址)送SI DI,OFFSET MEM2 ;目标数据块首地址(偏移地址)送DI CX,200 AL,[SI] [DI],AL SI DI CX NEXT
;数据块长度送CX(设循环次数) ;源数据块(各单元)内容送AL ;AL内容送目标地址 ;SI指向下一个单元 ;DI指向下一个单元 ;CX减1(修改循环次数) ;若循环没到200次,则继续 ;若已到200次,停止
NEXT: MOV MOV
INC INC DEC JNZ HLT
28
2)堆栈操作指令PUSH(push onto the stack)和POP(pop from the stack) (1)堆栈
堆栈是内存中一个特定的区域,用以存放各种必须保存的数据(举例说明,如用于保护断口地址,见P.109子程序调用示意图,又如对寄存器内容进行保护,见P.112)它在内存中所处的段称为堆栈段,其段基址放在堆栈段寄存器SS中。堆栈操作必须遵循以下原则:
·堆栈的存取每次必须是一个字。
·向堆栈中存放数据,是从高地址向低地址方向增长(与内存中其他段不同),从堆栈取数据时正好相反(见P.109图3-8)。 ·堆栈操作指令中的操作数只能是寄存器操作数或存储器操作数,而不能是立即数。 ·堆栈段在内存中的位置由堆栈段寄存器SS决定。堆栈指针SP总是指向栈顶,即SP的内容为当前栈顶偏移地址。所谓栈顶是一个存储单元,堆栈操作时,栈顶不参与操作,而把栈顶地址减1和栈顶地址减2这两个单元作为操作对象。 ·堆栈操作遵循“后进先出(LIFO)”的原则。 (2)堆栈操作指令
堆栈操作指令有两条,分别为压栈指令PUSH和弹出指令POP. 指令格式为: PUSH src POP dest
该两条指令中的操作对象可为:
·寄存器(包括数据寄存器,地址指针寄存器和变址寄存器)
·段寄存器(CS除外,PUSH CS合法,而POP CS非法) ·存储器单元
注意操作数必须为16位(即一个字)。如为寄存器必须为16位寄存器。如为存储器,则应是两个连续的存储单元。例如:
PUSH AX PUSH BP
PUSH DATA[SI] POP DS POP
[BX]
;AX内容压入堆栈
;基址寄存器内容压入堆栈
;以DS内容为段基址,将以(SI)+ DATA为偏移地址及 ;(SI)+ DATA + 1为偏移地址的两个单元内容压入堆栈 ;堆栈顶部两单元内容弹回DS段寄存器
;堆栈顶部两单元内容弹回以DS内容为段基址,以(BX) ;为偏移地址及以(BX)+ 1为偏移地址的两个单元
(3)堆栈指令的执行过程
压栈指令PUSH OPRD 执行过程参见P.110图3-10。 OPRD高8位→((SP)- 1); OPRD低8位→((SP)- 2); (SP)→(SP)- 2。
即PUSH指令将一个字的源操作数送到堆栈的顶部。 出栈指令POP OPRD 执行过程参见P.110图3-11。 ((SP))→OPRD低8位; ((SP)+ 1)→OPRD高8位;
(SP)+ 2→(SP)。
POP指令将栈顶两个单元的内容(一个字)送到目标地址中。
在程序中PUSH和POP指令一般成对出现,且执行次序相反,从而保证数据合理返回。
29
堆栈操作指令应用举例:
例:执行下列程序,分析堆栈区的变化情况。 MOV AX,9000H MOV SS,AX MOV SP,0E200H MOV PUSH PUSH ┆ POP POP
DX,38FFH DX AX DX AX
执行结果如P.111图3-12所示。
本例程序中,由于没遵循“后进先出”的原则,结果出栈后,AX和DX的内容没保持压 栈前的状态,而是AX和DX的内容进行了互换。
3)交换指令XCHG(exchange) 指令格式为:
XCHG OPRD1,OPRD2 ;(OPRD1)←→(OPRD2)
指令的操作功能是使源操作数和目标操作数的内容进行互换。 交换指令对操作数有如下要求:
·可以在寄存器与寄存器、寄存器与存储器之间进行数据交换,但不能在存储器与存储器之间进行数据交换。
·段寄存器内容不能参与交换。 ·两个操作数的字长必须相同。 例如:
XCHG AX,BX ;(AX)←→(BX) XCHG CL,DL
XCHG指令应用举例:
;(CL)←→(DL)
例:设(DS)= 2000H,(SI)= 0230H,(DL)= 88H,(20230H)= 44H,试析执行指令
XCHG [SI],DL后的结果。
解:执行后:(DL)= 44H,(20230H)= 88H。
即DL的内容与20230H单元的内容进行了交换。 4)查表转换指令XLAT(translate) 指令格式为: XLAT
或XLAT src table XLAT指令应用举例:
;(AL)←((BX)+(AL)) ;(src table为表的首地址)
例:在内存的数据段中存有一个数字符0~9的ASCII码转换表(见P112图3-13),首地址为Hex table,试编程,求数字符8的ASCII码。
程序如下:
LEA MOV
BX, Hex table AL,8
;表首偏移地址送BX ;8送AL
XLAT Hex table ;查表转换,结果在AL中 执行结果:(AL)= 38H
需要指出的是:由于要查找元素的序号规定放在AL中,所以表格的最大长度不会越过
30