欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

8086指令系统

程序员文章站 2024-02-01 18:36:10
...

首先定义出要用的符号

OPRD 泛指各种类型的操作数
mem 存储器操作数
acc 累加器操作数
dest 目标操作数
src 源操作数
disp 8位或16位偏移量,可用符号地址表示。
DATA 8位或16位立即数
port 输入输出端口
[ ] 表示存储器操作数,方括号内表示数据的偏移地址

数据传送指令

数据传送指令按功能分为四小类:通用数据数据传送指令,目标地址传送指令,标志传送指令,输入输出指令。

通用传送指令

通用数据传送指令包括一般传送指令mov,堆栈操作指令push或pop,交换指令xchg,查表转化指令xlat和字位扩展指令。

一般传送指令MOV

指令格式及操作:mov dest,src,这里,dest表示目标操作数,src表示源操作数。指令的功能是将一个操作数从源地址传送到目标地址,而源地址中的数据保持不变。

指令中的操作数可以是8位,也可以是16位,一次传送的数据到底是字节还是字取决于指令中涉及的寄存器是8位还是16位的。

(1)寄存器与寄存器或寄存器与段寄存器之间的传送,例如

mov bx,si ;将变址寄存器si中的内容送到基址寄存器bx
mov ds,ax ;将累加器ax中的内容送到段寄存器ds
mov al,cl ;将通用寄存器cl中的内容送到al

(2)寄存器与存储器之间的传送。mov指令可以在寄存器和存储器之间进行数据传送,若传送的是字操作符,那么 将对连续两个存储器进行存取,且寄存器的高8位对应存储器的高地址单元,寄存器的低8位对应存储器的低地址单元。

例如:若有DS=6000H,SS=8000H,AX=1234H,BX=1200H,DI=0383H,BP=1020H则有

mov [bx],ax ;将ax的内容送到内存单元,其中[61200H]=34H,[61201H]=12H
mov cl,[bp][di] ;将堆栈段中偏移地址为BP+DI=13A3H单元的内容送到CL,即物理地址为813A3H单元的内容送到CL
mov ax,[6000H] ;将DS段的6000H和6001H两个单元的内容送ax

(3)立即数到寄存器的传送

mov al,5 ;将立即数5送到累加器al
mov bx,3078h ;将立即数3078h送寄存器bx

(4)立即数到存储器的传送

mov byte ptr[bp+si],5 ;将5送到堆栈段中偏移地址为BP+SI所指的单元中。
mov word ptr[bx],1005h ;将1005h送数据段中偏移地址为BX和BX+1两单元。

(5)存储器与段寄存器之间的传送

mov ds,[1000h] ;将数据段中偏移地址为1000h字单元内容送到数据段寄存器ds
mov [bx],es ;将附加段寄存器es内容送到数据段中bx所指向的字单元

指令对操作数的要求

  1. mov指令中两个操作数字长必须相同,两个操作数可同为字节数或同为字操作数。

  2. 两个操作数不能同时为存储器操作数,若要在两个存储器单元之间进行数据传送,需用两条mov指令实现。

  3. 不能用立即数直接给段寄存器赋值,要实现此功能,需使用两条mov指令。

  4. 两个操作数不能同时为段寄存器,同样,要实现段寄存器到段寄存器的数据传送,需要两条mov指令。

  5. 一般情况下,指令指针IP及代码段寄存器的内容不通过mov指令修改,即它们不能作为目标操作数,但可以作为源操作数。

  6. 虽然许多指令的执行都对状态寄存器FLAGS的标志位产生影响,但通常情况下,FLAGS整体不能作为操作数。

例如:把内存中首地址为MEM1的200个字节送到首地址为MEM2的区域中。

题目分析:两个内存单元中的数据传送需要两条MOV指令实现,通过循环实现。

	  mov si,offset mem1 ;源数据块首地址(偏移地址)送入SI
	  mov di,offset mem2 ;目标首地址送入DI
	  mov cx,200 ;数据库长度送入cx,即=循环次数cx
next: mov al,[si] ;源数据块中当前字节送入AL
	  mov [di],al ;AL内容送目标地址,完成一个字节的传送
	  inc si ;SI+1,修改原地址指针
	  inc di ;DI+1,修改目标地址指针
	  dec cx ;CX-1,修改循环次数
	  jnz next ;若循环次数CX不等于0,则转移到next处
	  hlt ;暂停

堆栈操作指令PUSH和POP

(1)堆栈的概念。堆栈是内存中一个特定的区域,用以存放寄存器或存储器中暂停不用又必须保存的数据。它在内存中所处的段称为堆栈段,其段地址放在堆栈寄存器SS中。可以将堆栈看作是一个小存储器,但不能任意存取,必须遵守以下规则:

  1. 堆栈的存取每次必须是一个字(16位),即堆栈指令中的操作数必须是16位,即堆栈指令中的操作数必须是16位,而且只能是寄存器或存储器操作数,不能是立即数。
  2. 向堆栈中存放数据时,总是从高地址向低地址方向增长,而从堆栈取数据时则方向正好相反。
  3. 堆栈段在内存中的位置由SS决定,堆栈指针SP总是指向栈顶指针,即SP的内容等于当前栈顶的偏移地址。所谓栈顶是指当前可用堆栈操作指令进行数据交换的存储单元。在压入操作数之前,SP先减2,每弹出一个字,SP+2。
  4. 对堆栈的操作遵循“后进先出”的原则。

在程序调用时,堆栈主要应用于子程序调用、中断响应等操作时的参数保护,也可用于实现参数传递。

(2)堆栈操作指令。堆栈操作指令共有两条:压入堆栈指令PUSH和弹出堆栈指令POP。其格式为:

PUSH src
POP dest

指令中的操作数src和dest必须是字操作数(16位),它们可以是: 16位的通用寄存器或段寄存器,存储器单元。

push ax ;通用寄存器内容压入堆栈
push word ptr[data+si] ;数据段中两个连续存储单元内容压入堆栈
pop ds ;从栈顶弹出一个字到段寄存器
pop word ptr[bx] ;从栈顶弹出一个字到数据段两个连续内存中。

(3)堆栈指令的执行过程

  1. 压栈指令PUSH OPRD。PUSH指令是将指令中指定的字操作数压入堆栈。指令执行的过程为SP-2->SPOPRD高八位->[SP+1]OPRD低8位->[SP]
  2. 出栈指令POP OPRD。POP指令是将当前栈顶的一个字送到指令的目标地址,并紧接着修改堆栈指针,以使SP指向新的栈顶位置。指令的执行过程为:[SP]->OPRD低8位[SP+1]->OPRD高8位SP+2->SP

在程序中,PUSH和POP指令一般成对出现,且执行顺序相反,以保持堆栈原有状态,当然,在必要时也可通过修改SP的值来恢复堆栈原有状态。

堆栈除在子程序调用和响应中断时用于保护断点地址外,还可在需要时对某些寄存器内容进行保存。例如用CX寄存器同时作为两重循环嵌套的寄存器,可先将外循环计数值送CX,当内循环开始时将CX中的外循环计数值压入堆栈保存,然后把内循环计数写入CX,内循环完成后再将外循环计数值从堆栈中弹出CX。

交换指令XCHG

指令格式及操作:xchg oprd1,oprd2

交换操作就是将源地址与目标地址中的内容进行互换,即将源操作数送到目标操作数,同时将目标操作数传送源操作数。

交换指令对操作数的要求:

  1. 源操作数和目标操作数可以是寄存器或存储器,但不能同时为存储器。
  2. 不能为段寄存器操作数,即段寄存器的内容不能参加交换
  3. 两个操作数字长必须相同,可以是字节交换,也可以是字交换。

例如:设DS=2000H,SI=0230H,DL=88H,[20230H]=44H,执行指令xchg [si],dl,执行结果:[20230H]=88H,DL=44H。DL的内容与[20230H]的内容进行交换。

查表转换指令XLAT

XLAT是一条字节的查表转换指令,可以根据表中元素的序号查出表中相应元素的内容。

预先将要查找的代码排成一个表放在内存某区域中,指令要求将表的首地址(偏移地址)送寄存器BX,要查找的元素的序号送入AL(表中第一个元素的序号为0,然后依次为1,2,3)。执行XLAT指令后,表中指定序号的元素被存入AL。

指令格式:XLAT ;将偏移地址为BX+AL所指单元的内容送到AL中,或XLAT src_table ;src_table表示要查找的表的首地址

例如:在内存的数据段中存放有一张数值为0~9的ASCII码转换表,首地址为Hex_table,现要把数值8转换为对应的ASCII码,可用以下几条指令实现

LEA BX,Hex_table ;BX<-表首偏移地址 LEA指令将存储器操作数mem的4位16进制偏移地址送到指定的寄存器。
MOV AL,8 ;AL<-8
XLAT ;查表转换

结果为AL=38H,为8所对应的ASCII码。由于要查找元素的序号放在AL中,所以表格的最大长度不超过256个字节。

输入输出指令

输入输出指令是专门面向输入输出端口进行读写的指令,共有两条:IN和OUT,输入指令用于从I/O端口读数据到AL或AX中,而输出指令则把AL或AX的内容写出到I/O。在8088指令系统中,允许用两种形式表示端口地址:直接寻址,寄存器间接寻址。

  1. 直接寻址:指令中的I/O端口地址为8位,此时允许寻址256个端口,端口地址范围为0~FFH。
  2. 寄存器间接寻址:端口地址为16位,由DX寄存器指定,可寻址64K个端口,地址范围为0~FFFFH。

(1)输入指令IN:指令格式为in acc,port ;直接寻址,port为用8位立即数表示的端口地址in acc,DX ;间接寻址,16位端口由DX给出

IN指令从端口输入一个字节到AL或输入一个字到AX中。

(2)输出指令OUT:指令格式为out port,acc ;直接寻址,port为8位立即数表示的端口地址out dx,acc ;间接寻址,16位端口地址由DX给出

OUT指令将AL或AX的内容输出指定端口。

注意;采用间接寻址的IN/OUT指令只能用DX寄存器作为间址寄存器。

取偏移地址指令

指令格式:lea reg16,mem,lea指令将存储器操作数mem的16位偏移地址送到指定的寄存器。

lea bx,buffer ;将内存单元buffer的偏移地址送bx
mov al,[bx] ;取出buffer中的第一个数据送al
mov ah,[bx+1] ;取出buffer中的第二个数据送ah

例如:若设BX=1000H,DS=6000H,[61050H]=33H,[61051H]=44H。比较以下两条指令的执行结果。

lea bx,[bx+50H] 
mov bx,[bx+50H]

第一条执行后BX=1050H,第二条指令执行后BX=4433H。

其他传送指令

指令类型 汇编格式 指令的操作 示例
字位扩展指令 CBW 将AL中的字节数扩展为字,并存放在AX中,扩展的原则是:将符号位扩展到整个高位 MOV AL,8EH
CBW
;AX=FF8EH
字位扩展指令 CWD 将AX的字扩展为双字,扩展后高16位放在DX中,扩展的原则与CBW指令相同。 MOV AX,438H
CBW
;AX=438EH.DX=0000H
远地址传送指令 LDS reg16,mem32 mem32为内存中连续4个单元的首地址,指令将[mem32]和[mem32+1]单元内容送入reg16,将[mem32+2]和[mem32+3]单元的内容送DS。 设1234H为首的4个单元内容分别为11H,22H,00H,90H,则执行完lds si,[1234H],SI=2211H,DS=9000H

算术运算指令

算术运算涉及运算结果是否溢出,无符号数和有符号数的表示方法、数的可表示范围及溢出标志都不一样。有符号数的溢出是一种出错,而无符号数溢出则不能简单的认为是出错,也可看作是向更高位的进位。它们的判断标志分别为CF和OF。

加法指令

普通加法指令ADD

指令格式:ADD OPRD1,OPRD2,将源操作数和目标操作数相加,结果送回目标地址中。

这里,源操作数OPRD2和目标操作数OPRD1均可以是8位或16位的寄存器或存储器操作数,源操作数可以是立即数,可以是无符号数,也可以是带符号数。

以下指令是合法的

add cl,20h
add dx,[bx+si]

以下指令是非法的

add [si],[bx]
add ds,ax

ADD指令的执行对全部6个状态标志位都会产生影响。

  1. AF=1 表示 D 3 D_3 D3 D 4 D_4 D4有进位。
  2. CF=0 表示最高位向前无进位。
  3. OF=1 表示若为有符号数加法,其运算结果产生溢出。
  4. PF=0 表示8位的运算结果中,“1”的个数为奇数。
  5. SF=1 表示运算结果的最高位为“1”
  6. ZF=1 表示运算结果不为“0”

带进位的加法指令ADC

指令格式:ADC OPRD1,OPRD2,ADC指令与ADD指令功能、格式及对标志位的影响上都基本相同。只是CF也要参与运算。

加1指令INC

指令格式:INC OPRD,INC指令是将指定操作数的内容加1,再送回操作数。这里的操作数OPRD可以是寄存器或存储器数,可以是8位,也可以是16位数,但不能是段寄存器,也不能是立即数。INC指令不影响CF标志,但对其他5个标志位AF,OF,PF,SF,ZF会产生影响。

减法运算

8086/8088共有5条减法指令,不考虑借位的普通减法指令SUB,考虑借位的减法指令SBB,减1的指令DEC,求补指令NEG,比较指令CMP。

指令名 指令格式 指令功能 注意
SUB SUB OPRD1,OPRD2 目标数减去源操作数,并将结果送入目标操作数的地址。不考虑借位。 对操作数和影响标志位与ADD相同。
SBB SBB OPRD1,OPRD2 目标操作数减去源操作数和CF的值,并将结果送目标操作数的地址。 其对标志位的影响与SUB相同。
DEC DEC OPRD 将操作数的值减1,结果送回操作数地址。 其对标志位的影响与INC相同。
NEG NEG OPRD 用0减去操作数OPRD,结果返回操作数地址。 执行后,一般CF=1,除非给定操作数为0,则CF=0
CMP CMP OPRD1,OPRD2 用目标操作数减去源操作数,改变标志位情况判断大小 ZF=1,相等。ZF=0,不相等。
对两个无符号数,CF=0,则被减数大于减数。
对有符号数, O F ⊕ S F = 0 OF \oplus SF=0 OFSF=0,被减数大于减数。

乘法指令

MUL OPRD

指令的操作

  1. 字节乘法 A X ← O P R D × A L AX \leftarrow OPRD \times AL AXOPRD×AL
  2. 字乘法 D X : A X ← O P R D × A X DX:AX \leftarrow OPRD \times AX DX:AXOPRD×AX

源操作数可以是8位或16位的寄存器或存储器,乘法指令要求操作数字长相等,且不能为立即数。

除法指令

DIV OPRD

指令的操作

  1. 字节除法 A L ← A X / O P R D , A H ← A X % O P R D AL \leftarrow AX/OPRD,AH \leftarrow AX \% OPRD ALAX/OPRD,AHAX%OPRD

  2. 字除法 A X ← D X : A X / O P R D , D X ← D X : A X % O P R D AX \leftarrow DX:AX/OPRD,DX \leftarrow DX:AX \% OPRD AXDX:AX/OPRD,DXDX:AX%OPRD

逻辑运算和移位指令

逻辑运算

指令名 指令格式 指令功能
AND AND OPRD1,OPRD2 OPRD1 = OPRD1 & OPRD2
OR OR OPRD1,OPRD2 OPRD1 = OPRD1 | OPRD2
NOT NOT OPRD OPRD = !OPRD
XOR XOR OPRD1,OPRD2 O P R D 1 = O P R D 1 ⊕ O P R D 2 OPRD1 = OPRD1 \oplus OPRD2 OPRD1=OPRD1OPRD2

非循环移位指令

指令名 指令格式 指令功能
SAL SAL OPRD,1 SAL OPRD,CL SAL指令的操作将目的操作数的内容CL中所指定的位数。每左移一位,左边的值存入CF。
SAR SAR OPRD,1 SAR OPRD,CL SAR是将目标操作数视为有符号数,最高位不是补零,而是保持不变。右边的值存入CF。
SHL SHL OPRD,1 SHL OPRD,CL SHL指令的操作将目的操作数的内容CL中所指定的位数。每左移一位,左边的值存入CF。
SHR SHR OPRD,1 SHR OPRD,CL SHR指令的操作将目的操作数的内容CL中所指定的位数。每右移一位,右边的值存入CF。

串操作指令

所有串操作指令都具有以下特点

  1. 源串默认为数据段,即段基地址在DS中,但允许重设,偏移地址用SI寄存器指定,即源串指针为DS:SI。
  2. 目标串默认在ES附加段中,不允许段重设。偏移地址用DI寄存器锁定,即目标指针为ES:DI。
  3. 串长度值放在CX寄存器中。
  4. 串操作指令本身可实现地址指针的自动修改。
指令名 指令格式 指令功能
MOVS MOVS OPRD1,OPRD2 OPRD1为目标地址,OPRD2为源地址,指令将源地址字节或字传送给到目标地址中。
MOVSB MOVSB 源串在数据段,偏移地址在SI中,目标串在附加段,偏移地址在DI中。一次完成一个字节的传送。
MOVSW MOVSW 源串在数据段,偏移地址在SI中,目标串在附加段,偏移地址在DI中。一次完成一个字的传送。
CMPS CMPS OPRD1,OPRD2 将源串地址与目标串地址的数据按字节或字进行比较,结果反应到标志位。
CMPSB CMPSB 一次完成一个字节比较
CMPSW CMPSW 一次完成一个字比较

程序控制指令

无条件转移指令JMP

指令格式:JMP LABEL,LABEL是一个标号,也称为符号地址,表示转移的目的地。

JMP指令的操作是无条件地使程序转移到指定的目标位置,并从该地址开始执行新的程序段。

条件转移指令JCC

JCC指令 中文含义 检查符号位
JZ/JE 若为0则跳转;若相等则跳转 ZF=1
JNZ/JNE 若不为0则跳转;若不相等则跳转 ZF=0
JS 若为负则跳转 SF=1
JNS 若为正则跳转 SF=0
JP/JPE 若1出现次数为偶数则跳转 PF=1
JNP/JPO 若1出现次数为奇数则跳转 PF=0
JO 若溢出则跳转 OF=1
JNO 若无溢出则跳转 OF=0
JC/JB/JNAE 若进位则跳转;若低于则跳转;若不高于等于则跳转 CF=1
JNC/JNB/JAE 若无进位则跳转;若不低于则跳转;若高于等于则跳转; CF=0
JBE/JNA 若低于等于则跳转;若不高于则跳转 ZF=1或CF=1
JNBE/JA 若不低于等于则跳转;若高于则跳转 ZF=0或CF=0
JL/JNGE 若小于则跳转;若不大于等于则跳转 SF != OF
JNL/JGE 若不小于则跳转;若大于等于则跳转; SF = OF
JLE/JNG 若小于等于则跳转;若不大于则跳转 ZF != OF 或 ZF=1
JNLE/JG 若不小于等于则跳转;若大于则跳转 SF=0F 且 ZF=0

循环控制指令

LOOP指令

指令格式:LOOP LABEL,指令的执行是先将CX减1,再判断CX是否为0,若CX不为0,则转至目标地址继续循环。

LOOPZ指令

指令格式:LOOPZ LABEL,指令的执行先将CX减1,再根据CX的值及ZF的值判断是否继续循环。继续循环的条件是CX不为0,ZF为1。若CX=0或ZF=0,退出循环。

中断指令

INT指令

指令格式:INT n,CPU根据n计算中断向量的地址,然后从该地址取出中断服务程序的入口地址,并转到中断服务子程序去执行。

IRET指令

IRET为中断返回指令,用于从中断服务子程序返回到被中断的程序继续执行。任何中断服务子程序无论是外部还是内部中断,其最后一条指令都是IRET指令。

处理器控制指令

CLC:清进位标志位CF。

STC:进位标志位置位。

CMC:进位标志位取反。

CLD:DF置0。

STD:DF置1。

CLI:IF置0。

STI:IF置1。

相关标签: 汇编程序设计