汇编语言的指令系统和寻址方式

        计算机通过执行指令序列来使机器得以工作,所以对于每一系列的计算机都有指定的一组指令集供计算机使用,这组指令集就叫做计算机的指令系统;指令可分为操作码和操作数两部分,计算机执行指令时将根据对应的二进制代码识别操作码并加以执行操作码对应的操作;

        操作数部分比较复杂,每一条指令可根据操作数的个数分为一地址指令、二地址指令和三地址指令,其中三地址指令中有两个操作数是源操作数加以运算后的结果存放在第三个操作数对应的地址单元中;二地址指令是将两个操作数运算过后的结果存放在第一个操作数对应的地址单元里,所以这种操作将会使一位操作数损失,若以后还需用到该操作数应加以提前保存副本;寻找操作数的方式相对的复杂一些,以下将做重点介绍。

        另外汇编语言是一种符号语言,用助记符表示操作码,用符号或者符号地址表示操作数,且每一条都与机器指令一一对应;这篇文章将从80X86的寻址方式、程序占有的空间和执行时间和80X86的指令系统三个方面进行说明;(以80X86讲起)

一:80X86的寻址方式

        有两个方面:与数据有关的寻址方式和与转移地址有关的寻址方式。数据寻址方式中将以MOV     D,S为例,表示把源操作数S传送到目的操作数D中;

数据寻址方式:

1、立即寻址方式

      操作数直接存放在指令中,作为指令的一部分存放在代码段中,并且紧跟在操作码之后;这种方式常常用来表示常数,对寄存器进行赋值,源操作数的长度应该和目的操作数的长度一致;如:

MOV      AX,3064H


汇编语言的指令系统和寻址方式_第1张图片
OP表示操作码3064为立即数

2、寄存器寻址方式

        操作数在寄存器中,不需要访问存储器,所以有较高的运算速度;如:

MOV     AX,BX

若执行前(AX)=3064H,(BX)=1234H,执行后(AX)=(BX)=1234H


汇编语言的指令系统和寻址方式_第2张图片
寄存器寻址方式


3、直接寻址方式

      这种方式操作数的有效地址只有位移量一种成分;如:

MOV     AX,[2000H]

如果(DS)=3000好,执行如图:

汇编语言的指令系统和寻址方式_第3张图片
指令保存以及执行情况

另:用符号地址代替数值地址

MOV     AX,VALUE和MOV     AX,[VALUE]是等效的

4、寄存器间接寻址方式

        操作数的有效地址只包含基址寄存器或者变趾寄存器内容一种成分;另外,16位寻址时除BP寄存器默认段寄存器为SS外,其它的默认寄存器为DS;

如:MOV     AX,[BX]

若(DS)=2000H,(BX)=1000H,则:物理地址=20000+1000=21000H,结果为(AX)=50A0H;执行如下

汇编语言的指令系统和寻址方式_第4张图片
存储以及执行情况


5、寄存器相对寻址方式

        操作数的有效地址为基址寄存器或变址寄存器的内容与指令中指定的位移量两种成分构成,即两种成分相加即为有效地址;

如:MOV     AX,COUNT[SI]

也可以表示为MOV     AX,[count+si](不区分大小写);若:(ds)=3000h,(si)=2000h,count=3000h,物理地址=30000+2000+3000=35000H,执行结果(ax)=1234h;执行情况如下:


汇编语言的指令系统和寻址方式_第5张图片
指令存储以及执行情况

6、基址变址寻址方式

      操作数的有效地址有两种成分构成,即变址寄存器内容和基址寄存器内容之和;

如:mov     ax,[bx][di]或者写为mov     ax,[bx+di];若(ds)=2100h,(bx)=0158h,di=10A5h;物理地址=21000+0158+10A5=221FDH;执行结果(ax)=1234H;如下:

汇编语言的指令系统和寻址方式_第6张图片
指令执行以及存储

7、相对基址变址寻址方式

操作数的有效地址是一个基址寄存器与一个变址寄存器的内容和指令中指定的位移量之和,故有三种成分构成;

如:mov     ax,array[bx][si];若(ds)=3000h,(bx)=2000h,(si)=1000h,mask=0250h;物理地址=16d*3000+2000+1000+0250=33250h;执行如下:

汇编语言的指令系统和寻址方式_第7张图片
指令存储以及执行

与转移地址有关的寻址方式:

1、段内直接寻址

        转向的有效地址为当前IP内容与指令中指定的8位或16位位移量之和;当用于条件转移时,位移量只允许8位;当用于无条件转移时,位移量为8位时表示段内短转移,此时须在位移量之前加上short字符,如jmp     short quest;无条件转移位移量为16位时,称为段内近转移,须在位移量前加操作符near ptr,如:jmp     near ptr quest;其中quest为位移量符号;

汇编语言的指令系统和寻址方式_第8张图片
段内直接寻址

2、段内间接寻址

        这种转移转向的有效地址是寄存器或者存储单元里的内容,也就是将寄存器或者存储单元里的内容取代以前IP寄存器里的内容;这种段内转移指令不能作为条件转移指令使用;如:

jmp     bx

jmp     word ptr[bp+table]


汇编语言的指令系统和寻址方式_第9张图片
段内间接

注意:这里的转向的有效地址是指根据寻址方式得到的存储单元或者寄存器里的内容;

3、段间直接寻址

这种转移方式除了将指令中指定的偏移地址取代IP寄存器里的内容外,还需要将指令中指定的内容所在的段地址取代cs段里内容,此时用far ptr操作符表示;如:

jmp     far ptr nextroutint


汇编语言的指令系统和寻址方式_第10张图片
段间直接

4、段间间接转移

        用存储器里两个连续的字来取代cs和ip的内容,此时存储器里的内容可以用除立即数以外的任意一种数据寻址方式获得;若用此方式须在指令中加以dword ptr字符,如:

jmp     dword ptr[inters+bx]

汇编语言的指令系统和寻址方式_第11张图片
段间间接


二、程序占有的空间和执行时间

       对于一条指令来说,若为16位则一条指令的长度可达到1至7个字节,而对于不同的寻址方式使用操作数也需要时间这就在空间和时间上有了限制,所以编制程序时应考虑这两个因素使程序更加的精炼;

三、80X86的指令系统

        此系列的指令系统可以分别为以下六组:数据传送指令、串处理指令、算术指令、控制转移指令、逻辑指令和处理机控制指令,此处不对处理机控制指令作说明,有兴趣者可自己查阅相关书籍;

数据传送指令:

这种指令负责把数据、地址或者立即数传送到寄存器或者存储单元中,有以下五类,分别作以下说明;

1、通用数据传送指令

mov传送指令:

格式:mov     dst,src;

执行的操作:(dst)←(src);其中,dst为目的操作数,src为原操作数;

       在此指令中需要注意以下规则:两个操作数不能同时为存储单元、立即数不能作为目的操作数使用、不能在两个段寄存器间传送信息,立即数不能直接送至段寄存器、目的操作数不允许用cs寄存器;另外以下是允许操作类型:寄存器到寄存器、立即数到寄存器、立即数到存储单元、存储单元到寄存器、寄存器到存储单元、寄存器或存储单元到除cs段外的任何段寄存器;此指令不影响标志位;

如 mov     ax,data_seg       mov     ds,ax

push进栈:

格式:push src

执行操作:

16位指令(sp)←(sp)-2

               ((sp+1),(sp))←(src)

如:  push ax

执行情况如下:      

汇编语言的指令系统和寻址方式_第12张图片
push操作

注意此操作不能用立即数方式;

pop出栈指令:

格式:    格式:pop dst

执行操作:

16位指令(dst)←((sp+1),(sp))

             (sp)←(sp)+2

如:   pop ax

执行如下:


汇编语言的指令系统和寻址方式_第13张图片
出栈操作

注意此操作目的操作数不允许用立即数和cs段寄存器;  

xchg交换指令:

格式:xchg opr1,opr2

执行操作:(opr1)与(opr2)内容互换

此指令不允许使用立即数方式,不允许使用段寄存器,而且必须有一个操作数为寄存器,不影响标志位;如:

xchg bx,[bp+si]

2、累加器专用传送指令

      这组指令实现在I/O端口和CPU之间传送信息,且CPU接收信息的寄存器只限于AX和AL;外部设备利用i/O端口号来收发信息,i/o端口号最多可有65536个i/o端口,其中前256个端口(0~0FFH)可以直接在指令中指定,此时指令用两个字节表示,第二个字节就是要表示的端口号,这种方式称为长格式;另外,当端口号>=256时,只能使用短格式,必须将端口号先传送到DX寄存器,然后将DX的内容传送到AX、AL或者EAX寄存器中;

      这组指令不影响标志位;

in输入指令:

长格式:in al,port(字节)、in ax,port(字);

执行的操作:(al)←(port)(字节)、(ax)←((port+1),(port))(字);

短格式:in al,dx(字节)、in ax,dx(字);

执行的操作:(al)←((dx))(字节)、(ax)←((dl+1),(dl));

长格式如:in ax,28h

短格式如:

mov dx,3FCH    

in ax,dx

out输出指令:

长格式:out port,al(字节)、out port,ax(字);

执行的操作:(port)←(al)(字节)、((port+1),(port))←(ax)(字);

短格式:out dx,al(字节)、out dx,ax(字);

执行的操作:((dx))←(al)(字节)、((dl+1),(dl))←(ax);

长格式如:out 28h,al

短格式如:

mov dx,ax

out 3FCH,dx

3、地址传送指令

LEA(load effective address)有效地址送寄存器指令

    这种方式实现把源操作的有效地址传送到寄存器中,注意此种方式的源操作数的寻址方式只能使用出立即数和寄存器之外的存储器寻址方式的任意一种;目的操作数可使用16位的除段寄存器之外的寄存器;此指令不影响标志位;

格式:lea bx,[bx+si+0F62H]

如执行之前(bx)=0400H,(si)=003cH

执行后:(bx)=0400+003c+0f62=139eh

辨异:上述例子是把源操作数的有效地址送到bx中,mov bx,[bx+si+0F62H]则是把源操作数指定的存储单元的内容送到bx中,需要计算物理地址;

LDS(load ds with pointer)、LES(load es with pointer)指针送寄存器指令

      这种方式的源操作数只能用于存储器寻址的任一种方式,且目的操作数的寄存器不能使用段寄存器;该指令是把源操作数的指定的存储单元的内容送到目的操作数中,再把源操作数存储单元的下一个存储单元的内容送到指定的存储器中;另外这组指令不影响标志位;以LDS指令为例,LES指令操作和LDS操作原理相同,只是指定的寄存器不同;

格式:LDS REG,SRC

执行的操作:

(REG)←(SRC),(DS)←(SRC+2)

如:LES DI,[BX]

执行前:(DS)=B000H,(BX)=080AH,(0B080AH)=05AEH,(0B080CH)=4000h

执行后:(DI)=05AEH,(ES)=4000H

4、标志寄存器传送指令

LAHF(load ah with flags)标志送AH

格式:lahf      

执行的操作:(ah)←(flags的低字节)

SAHF(store ah into flags)AH标志送至flags寄存器

格式:sahf

执行的操作:(flags的低字节)←(ah)

另还有pushf/pushfd、popf/popfd此处不作介绍,注意这组指令不影响标志位;

5、类型转换指令

CBW(convert byte to word) 字节转换为字指令

格式:cbw

执行的操作:将al中的内容扩展到ah中,若(al)最高有效位为0,(ah)为0;若(al)的最高有效位为1,则(ah)为0FFH;

算术指令:

      该指令有双操作数和单操作数之分,双操作数不允许目的操作数和源操作数同时为存储器寻址方式单操作数不允许使用立即数方式;

1、加法指令

ADD(add)加法:

格式:add dst,src

执行的操作:(dst)←(dst)+(src)

此操作影响标志位;

ADC(add with carry)带进位加法:

格式:adc dst,src

执行的操作:(dst)←(dst)+(src)+cf;cf为带进位的值;

此操作影响标志位;

INC(increment)加1:

格式:inc opr

执行的操作:(opr)←(opr)+1

此操作不影响标志位;

      上面指令提到add和adc指令影响标志位,标志位中最主要的是of(overflow flag)溢出标志、cf(carry flag)进位标志、zf(zero flag)零标志、sf(sign flag)符号标志;其中当结果为零时zf为1,否则为0;结果为负时sf为1,否则为0;考虑of位时须把操作数当成有符号数看待,对于加法来讲,若操作数符号相同结果的符号与之相反则of置为1,否则置为0;考虑cf位时须把操作数当成无符号数看待,最高有效位有进位时置为1,否则置为0;如下例:

add dx,0F0F0H;执行前(dx)=4652h

操作如下:0100 0110 0101 0010

                   +1111 0000 1111 0000

=0011 0111 0100 0010(有进位1)

看作有符号数:  则运算前符号相反故of=0,看作无符号数:有进位故cf=1;结果符号为正故sf=0;结果不为零故zf=0;

2、减法指令

SUB(subtract)减法指令:

格式:sub dst,src

执行的操作:(dst)←(dst)-(src);此操作影响标志位;

SBB(subtract with borrow)带借位减法:

格式:sub dst,src

执行的操作:(dst)←(dst)-(src)-cf;此操作影响标志位;

DEC(decrement)减1指令:

格式:dec opr

执行的操作:(opr)←(opr)-1;此操作不影响cf标志位;

CMP(compare)比较指令:

格式:cmp opr1,opr2

执行的操作:(opr1)-(opr2);此操作影响条件标志位;

      现在来说说减法对标志位的影响;对于zf和sf的设置同加法指令相同,这里不再赘述;设置of位时,把操作数看作有符号数,若被减数与减数的符号相反结果与减数的符号相同的话则of位置为1,否则置为1;设置cf位时,把操作数看作无符号数,若被减数<减数则cf置为1,否则置为0;如下例:

sub [si+14H],0136H;

指令执行之前(ds)=3000H,(si)=0040h,(30054h)=4336h;

如下:0100 0011 0011 0110

           -0000 0001 0011 0110

          =0100 0010 0000 0000

     作如下判断:结果不为零则zf位为0,结果为正则sf置为0,当成无符号数看待被减数>减数则cf置为0,当成有符号数看待,被减数与减数的符号相同,故of置为0;

3、乘法指令

指令中的源操作数的寻址方式可以是初立即数以外的任意一种方式;目的操作数为累加器;

MUL(unsigned multiple):无符号数乘法

格式:mul src

执行的操作:源操作数为8位则相乘得到的16位存放到AX,AH存放高位字节,AL存放低位字节;源操作数为16位时,结果存放到DX和AX中,DX存放高位,AX存放低位;此操作影响of位和cf位其它条件标志位没有定义;

iMUL(signed multiple):有符号数乘法

格式:imul src

执行的操作:和有符号数相同,不过此操作必须是带符号数;

      乘法对标志位的影响如下:对于无符号数来讲,若乘积的高一半为零则cf=of=0,否则为1;对于有符号数来讲,若乘积的高一半是低一半的字节的符号扩展,则cf=of=0,否则为1;如下例:

mul bl;指令执行前(al)=0B4H,(bl)=11H;

执行的结果为:0000 1011 1111 0100

结果的前一半不全为零,故cf=of=1;

4、除法指令

指令中的源操作数的寻址方式可以是初立即数以外的任意一种方式;目的操作数为累加器;

DIV(unsigned divided)无符号数除法指令:

格式:div src

执行的操作:若除数为8位,则被除数为16位且保存在ax中,相除得到的结果的8位商保存在al中,得到的8位余数保存在ah中;若除数为16位,则被除数为32位,高位保存在DX寄存器中,低位保存在AX中,相除得到的结果的16位商保存在ax中,得到的16位的余数保存在dx中;此指令对所有的条件码均无定义;

IDIV(signed divided)带符号数除法指令:

格式:idiv src

执行的操作:和div相同,但要求操作数必须为带符号数,商和余数也都是带符号数,且余数的符号和被除数相同;对所有的条件码均无定义;

逻辑指令:

1、逻辑运算指令

AND(and)逻辑与指令

格式:and dst,src

执行的操作为(dst)←(dst)∧(src);

OR(or)逻辑或指令

格式:or dst,src

执行的操作为(dst)←(dst)∨(src);

XOR(exclusive or)逻辑或指令

格式:xor dst,src

执行的操作为(dst)←(dst)∀(src);

TEST(test)测试指令

格式:test opr1,opr2

执行的操作:(opr1)∩(opr2);结果不保存,为了置条件码;

以上指令中,not指令不影响标志位,且操作符不能为立即数;其余指令两个操作数的寻址方式不能同时为存储器寻址,且执行后使of和cf置为0,af无定义,其余位根据结果设置;上面的指令对于处理操作数相应位比较有用,如要求屏蔽操作数的某些位只需利用add指令将源操作数相应位置为0,其余位置为1即可;要求将操作数的某些位置为1,则使用or指令令源操作数的相应位置为1,其余位置为0即可;要求测试某些位是否为1,利用test指令将相应位置为1,其余位置为零,若结果cf=of=0,zf=1,sf=0则测试的位不为1;要求对目的操作数的某些位取反,则需用xor指令将源操作数的相应位置为1即可;

2、移位指令

     以下指令的opr部分可以用除立即数以外的任意一种寻址方式,当移位次数为1时可用立即数1代替cnt符号,当移位次数超过1时,最好把需要移动的位数送到CL中然后将CL代替CNT符号即可;

SHL(shift logical left)逻辑左移

格式:shl opr,cnt

执行的操作如图:


汇编语言的指令系统和寻址方式_第14张图片
逻辑左移

SAL(shift arithmetic left)算术左移

格式:sal opr,cnt

执行操作和逻辑左移相同;

SHR(shift right)逻辑右移

格式:shr opr,cnt

执行操作如图:


汇编语言的指令系统和寻址方式_第15张图片
逻辑右移

SAR(shift arithmetic right)算术右移

格式:sar opr,cnt

执行操作如图:


汇编语言的指令系统和寻址方式_第16张图片
算术右移

ROL(rotat left)循环左移

格式:rol opr,cnt

执行操作如下:


汇编语言的指令系统和寻址方式_第17张图片
循环左移

ROR(rotat right)循环右移

格式:ror opr,cnt

执行操作如图:


汇编语言的指令系统和寻址方式_第18张图片
循环右移

RCL(rotat left through carry)带进位循环左移

格式:rcl opr,cnt

执行操作如图:


汇编语言的指令系统和寻址方式_第19张图片
带进位循环左移

RCR(rotat right through carry)带进位循环右移

格式:RCR opr,cnt

执行操作如下:


汇编语言的指令系统和寻址方式_第20张图片
带进位循环右移

上述指令对于cf位的影响如图,当cnt为1时,of条件标志有定义,否则有定义,移位过后当最高有效位发生变化时of位置为1,否则置为0;另外上述指令对于AF位无定义:

串处理指令:

这一系列指令根据组合使用可分为两组,以下做详细说明;

(一)、与rep指令组合使用的有movs,stos,lods,ins和outs指令

REP(repeat)重复指令

格式:rep string primitive

执行的操作:string primitive是指movs.stos.lods.ins指令,当要执行重复操作时,需要先将重复次数送入cx寄存器中;执行一次重复指令cx内容减1,直到cx内容为0停止执行;

MOVS(move string)串传送指令

指令:movs dst,src

执行的操作:((di))←((si))

指令movsb(字节)                                        

执行的操作:((di))+/-1←((si))+/-1

指令:movsw(字)                                          

执行的操作:((di))+/-2←((si))+/-2

      说明:此指令的功能是将SI寄存器指向的单元中的内容传送到DI指向的单元中,可顺序存储(DF=0,用cld指令设置),也可倒序存储(DF=1,用sed指令设置),使用此指令之前还需要将源串的偏移地址(倒序存储采用串的末地址)移到SI寄存器中,另外源串的段地址(倒序存储采用串的末地址)必须要送至数据段寄存器中也可使用段跨越前缀指定段寄存器;另外还需处理的是目的串的首地址(倒序存储采用串的末地址)送至DI寄存器中,目的串的段地址送至附加段中;该指令不影响条件码;

LODS(load from string)从串取指令

指令:lods(字节)

执行的操作:(al)←((si))

指令:lodsw(字)

执行的操作:(ax)=(al),(ah)←((si),(si+1))

操作说明:此指令的功能是将si指向的单元中的内容传送到AX或AL寄存器,可顺序存(DF=0,用cld指令设置),也可倒序存(DF=1,用sed指令设置),使用此指令之前还需要将源串的首地址(倒序存储采用串的末地址)送至sI寄存器中,目的串的段地址送至数据段中,允许使用段跨越来修改源段的段寄存器;该指令不影响条件码;该指令一般不经常和rep指令连用;

INS(input from port to string)串输入指令

指令:insb(字节)

执行的操作:((di))+/-1←((dx))

指令:insw(字)

执行的操作:((di))+/-2←((dx))

说明:把端口号内的内容存到指定的串单元中;

OUTS(output string to port)串输入指令

指令:outsb(字节)

执行的操作:((dx))←((si))+/-1

指令:outsw(字)

执行的操作:((dx))←((si))+/-2

说明:把源串里的内容送至端口号内;

(二)与REPZ/REPE(repeat while equal/zero)和REPNE/REPNZ(repeat while not equal/zero)连用的CMPS(compare string)和SCAS(scan string)      

REPZ/REPE当相等/为零时重复串操作

格式:repz/repe string primitive

string primitive可为cmps或scas指令

执行的操作:退出条件为zf=0(比较结果不为零即不相等此时cf标志位为0)或者cx循环次数为零,其余的操作和rep执行情况相同;

REPNZ/REPNE当相等/为零时重复串操作

格式:repnz/repne string primitive

string primitive可为cmps或scas指令

执行的操作:退出条件为zf=1(比较结果为零即量比较数相等此时cf标志位为0)或者cx循环次数为零,其余的操作和rep执行情况相同;

CMPS串比较指令

指令:cmpsb(字节)

执行的操作:将目的串和源串的相应字节相减,但不保存结果,只根据结果设置标志位;其余情况和movb相同;

指令:cmpsw(字)

执行的操作:将目的串和源串的相应字相减,但不保存结果,只根据结果设置标志位;其余情况和movb相同;

SCAS串扫描指令

指令:scasb(字节)

执行的操作:将AL寄存器里的内容和附加段目的串的字节相比较,但不保存结果,只根据结果设置标志位,其余情况和movs指令相同;

指令:scasw(字)

执行的操作:将AX寄存器里的内容和附加段目的串的字相比较,但不保存结果,只根据结果设置标志位,其余情况和movs指令相同;

控制转移指令:

这部分内容主要由无条件转移指令、条件转移指令、循环指令和子程序构成,其余在这里不作介绍;另外无条件转移指令在8086的寻址方式里已经介绍过,此处也不再赘述;

1、条件转移指令

这部分指令的opr部分使用了相对寻址方式,只能使用段内的短转移和近转移,若要进行段间的转移则要使用jmp指令;该部分指令不影响条件码,只根据一次运算的结果设置的条件判断是否需要进行跳转;条件转移指令可分为三类如下:

(1)根据单个条件标志的设置情况判断是否转移;

JZ/JE(jump if zero/equal)结果为零或者相等则进行转移

格式:jz\je opr

测试条件:zf=1

JNZ/JNE(jump if not zero/equal)结果不为零或者不相等则进行转移

格式:jnz\jne opr

测试条件:zf=0

JS(jump if sign)结果为负转移指令

格式:js opr

测试条件:sf=1

JNS(jump if not sign)结果不为负则进行转移

格式:jns opr

测试条件:sf=0

JO(jump if overflow)溢出则转移

格式:jo opr

测试条件:of=1

JNO(jump if not overflow)溢出则转移

格式:jno opr

测试条件:of=0

JB/JNAE/JC(jump if below,or not above or equal,or carry)低于,不高于或者进位为1转移指令

格式:jb/jnae/jc opr

测试条件:cf=1

JNB/JAE/JNC(jump if not below,or above or equal,or not carry)不低于,或者高于或者进位为零转移指令

格式:jnb/jae/jnc opr

测试条件:cf=0

2、比较两个无符号数,根据比较结果判断是否转移(高低用below或者above表示)

JB/JNAE/JC、JNB/JAE/jNC指令和上述情况相同;

JBE/JNA(jump if below or equal,or not above)比较结果为<=时转移

格式:jbe/jna opr

测试条件:cf∪zf=1

JNBE/JA(jump if not below or equal,or above)比较结果为>时转移

格式:jnbe/ja opr

测试条件:cf∪zf=0

3、比较两个有符号数,高低用greater和less表示

JL/JNGE(jump if less,or not greater equal)比较结果为<时转移指令

格式:jl/jnge opr

测试条件:sf∀of=1

JNL/JGE(jump if not less,or greater or equal)比较结果为>=时转移指令

格式:jnl/jge opr

测试条件:sf∀of=0

JLE/JNG(jump if less or equal,or not greater)比较结果为<=时转移指令

格式:jle/jng opr

测试条件:sf∀of∪zf=1

JNLE/JG(jump if not less equal,or greater)比较结果为>时转移指令

格式:jnle/jg opr

测试条件:sf∀of∪zf=0

2、循环指令

循环指令和串操作的重复指令相差不大,只是循环的可能是一段程序而不是只针对字符操作,循环的比较结果也循序标志位,另外循环操作次数也需要提前存入cx寄存器中,循环指令的opr部分则是使用8位位移量与当前ip寄存器内容相加,即相当于段内直接短转移;该指令不影响条件码指令如下:

LOOP(loop)循环指令

格式:loop opr

测试条件:cx≠0

LOOPZ/LOOPE(loop if zf=0)当结果为零即判断结果相等则执行循环

格式:loopz/loope opr

测试条件:cx≠0或者zf=1

LOOPNZ/LOOPNE(loop if zf=0)当结果为零即判断结果相等则执行循环

格式:loopnz/loopne opr

测试条件:cx≠0或者zf=0

3、子程序指令

      和高级语言相同的是汇编语言也提供了可以编写具有特定功能的程序,称为子程序;子程序由主程序通过CALL指令调用,在子程序的末尾设置RET指令用来当子程序执行完之后返回主程序;子程序可以和主程序设置在同一段中,也可以设置在不同段中,故CALL和RET指令就有不同的操作类型,这部分指令可以类比跳转指令来看待,只是多了一部分的在堆栈中保存主程序的返回地址,这部分指令不影响条件码;以下分别来说明:

(1)、CALL调用指令

段内直接近调用

格式:CALL DST

执行的操作:push(IP)

                    (IP)←(IP)+位移量

说明:指令中的DST即是指子程序中的第一条指令的地址;操作的第一步是将当前主程序的IP内容(当前主程序调用程序的下一条指令的地址)放置在栈中,第二步是将当前(IP)内容加上需要调用程序和当前程序之间的位移量放置到(IP)中;

段内间接近调用

格式:CALL DST

执行的操作:push(IP)

                   (IP)←(EA)

说明:指令中的DST可以使用初立即数之外的任意一种寻址方式;操作的第一步是将当前主程序的IP内容(当前主程序调用程序的下一条指令的地址)放置在栈中,第二步是将按寻址方式寻找到的存储单元中的有效地址放置到(IP)中;

段间直接远调用

格式:CALL DST

执行的操作:push(CS)            ;主程序所在的段地址

                     push(IP)             ;返回主程序的有效地址

       (IP)←(EA);按DST的寻址方式寻找到的存储单元内的内容作为子程序的有效地址

       (CS)←(EA+2);按DST的寻址方式寻找到的存储单元的下一单元内的内容作为子程序的有效地址

(2)、返回指令

返回指令是将主程序存入栈中的内容返回到IP和CS寄存器中,以便继续执行主程序的后续指令;如下

段内近返回

格式:RET 执行的操作,(IP)←POP()出栈操作

段内带立即数近返回

格式:RET EXP

执行的操作:第一步执行(IP)←POP(),第二步根据EXP表达式计算出的位移量修改栈顶指针,即(CS)←(CS)+位移量

段间近返回

格式:RET 执行的操作,依次执行(IP)←POP()出栈操作和(CS)←POP()出栈操作

段间带立即数近返回

格式:RET EXP

执行的操作:第一步执行(IP)←POP()和(CS)←POP(),第二步根据EXP表达式计算出的位移量修改栈顶指针,即(CS)←(CS)+位移量

你可能感兴趣的:(汇编语言的指令系统和寻址方式)