zoukankan      html  css  js  c++  java
  • 汇编语言--微机CPU的指令系统(五)(数据传送指令)

    五、微机CPU的指令系统

    1、汇编语言指令格式

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

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

    指令助忆符体现该指令的功能,它对应一条二进制编码的机器指令。指令的操作数个数由该指令的确定,可以没有操作数,也可以有一个、二个或三个操作数。绝大多数指令的操作数要显式的写出来,但也有指令的操作数是隐含的,不需要在指令中写出。

    当指令含有操作数,并要求在指令中显式地写出来时,则在书写时必须遵守:

    l 指令助忆符和操作数之间要有分隔符,分隔符可以是若干个空格或TAB键;

    l 如果指令含有多个操作数,那么,操作数之间要用逗号","分开。

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

    对指令还要掌握以下几个方面内容:

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

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

    l 指令的执行时间,对可完成同样功能的指令,要选用执行时间短的指令。

    2、指令系统

    通常,把指令按其功能分成以下几大类:

    l 数据传送指令

    l 标志位操作指令

    l 算术运算指令

    l 逻辑运算指令

    l 移位操作指令

    l 位操作指令

    l 比较运算指令

    l 循环指令

    l 转移指令

    l 条件设置字节指令

    l 字符串操作指令

    l ASCII-BCD码运算调整指令

    l 处理器指令

    (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]

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

    源操作数是立即数

    MOV AL, 89H MOV BX, -100H MOV EDX, 12345678H

    MOV VARW, 200H MOV [BX], 2345H MOV [BX+DI], 1234H

    在汇编语言中,主要的数据传送方式如图5.1所示。虽然一条MOV指令能实现其中大多数的数据传送方式,但也存在MOV指令不能实现的传送方式。

    clip_image002

    对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)、两个操作数不能同时为存储单元,如:MOV VARA, VARB等,其中VARA和VARB是同数据类型的内存变量。

    对于规定2、4和7,我们可以用通用寄存器作为中转来达到最终目的。表5.1列举一个可行的解决方案,仅供参考。读者可考虑用其它办法来完成同样的功能。

    clip_image004

    对于情况1:不同位数数据之间的传送问题,在80386及其以后的CPU中,增加一组新的指令——传送-填充指令,它可把位数少的源操作数传送给位数多的目的操作数,多出的部分按指令的规定进行填充。

    2、传送—填充指令(Move-and-Fill Instruction)

    传送—填充指令是把位数短的源操作数传送给位数长的目的操作数。指令格式如下:

    MOVSX/MOVZX Reg/Mem, Reg/Mem/Imm ;80386+

    其中:80386+表示80386及其之后的CPU,其它类似符号含义类同,不再说明。

    指令的主要功能和限制与MOV指令类似,不同之处是:在传送时,对目的操作数的高位进行填充。根据其填充方式,又分为:符号填充和零填充。

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

    clip_image006

    ž 符号填充指令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所示。

    clip_image008

    例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等置初值之用。其功能如图5.4所示。

    clip_image010

    例如:

    BUFFER 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、LSS(Load Stack Segment Register)是80386及其以后CPU中才有的指令。

    若Reg是16位寄存器,那么,Men必须是32位指针;若Reg是32位寄存器,那么,Men必须是48位指针,其低32位给指令中指定的寄存器,高16位给指令中的段寄存器。指令的执行结果如图5.5所示。

    clip_image012

    例如:

    POINTER DD 12345678H

    LDS BX, POINTER

    指令的执行结果如图5.5所示。各寄存器的内容分别为:(BX)=5678H,(DS)=1234H。

    6、堆栈操作指令(Stack Operation Instruction)

    堆栈是一个重要的数据结构,它具有“先进后出”的特点,通常用来保存程序的返回地址。它主要有两大类操作:进栈操作和出栈操作。

    1)、进栈操作

    a) PUSH(Push Word or Doubleword onto Stack)

    指令格式:PUSH Reg/Mem

    PUSH Imm ;80286+

    一个字进栈,系统自动完成两步操作:SP←SP-2,(SP)←操作数;

    一个双字进栈,系统自动完成两步操作:ESP←ESP-4,(ESP)←操作数。

    b) PUSHA(Push All General Registers)

    指令格式:PUSHA ;80286+

    其功能是依次把寄存器AX、CX、DX、BX、SP、BP、SI和DI等压栈。

    c) PUSHAD(Push All 32-bit General Registers)

    指令格式:PUSHAD ;80386+

    其功能是把寄存器EAX、ECX、EDX、EBX、ESP、EBP、ESI和EDI等压栈。

    2)、出栈操作

    a) POP(Pop Word or Doubleword off Stack)

    指令格式:POP Reg/Mem

    弹出一个字,系统自动完成两步操作:操作数←(SP),SP←SP-2;

    弹出一个双字,系统自动完成两步操作:操作数←(ESP),ESP←ESP-4。

    b) POPA(Pop All General Registers)

    指令格式:POPA ;80286+

    其功能是依次把寄存器DI、SI、BP、SP、BX、DX、CX和AX等弹出栈。其实,程序员不用记住它们的具体顺序,只要与指令PUSHA对称使用就可以了。

    c) 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所示。

    clip_image014

    简单例子:

    X DW 1122H,3344H,5566H,7788H。

    LEA  BX,X。

    MOV  AL,03H。

    XLAT。

    结果AL为33H。

    XLAT作用:将((BX)+(AL))送给(AL)----简单:将BX为首地址的,偏移地址为AL的内容送给AL。

    在运行XLAT之前,AL=3 BX=(X的首地址)。

    这时BX+AL就是33....为什么?注意高地址放在下面。

    22------BX指向这里。

    11。

    44。

    33-----偏移地址AL为3的位置就是这里。

    XLAT X。

    在执行XLAT之前,先将X的地址送给BX,偏移次数送给AL。

    XLAT即为查找指令 (一个字节)。

    8、I/O指令

    有关I/O指令将在后面I/O指令中介绍,在此从略。

  • 相关阅读:
    BZOJ 3709: [PA2014]Bohater
    BZOJ 3689: 异或之
    BZOJ 4385: [POI2015]Wilcze doły
    2017-2018 ACM-ICPC German Collegiate Programming Contest (GCPC 2017) Solution
    Codeforces Round #522 (Div. 2, based on Technocup 2019 Elimination Round 3) Solution
    BZOJ 4320: ShangHai2006 Homework
    BZOJ 4318: OSU!
    2016-2017 ACM-ICPC CHINA-Final Solution
    BZOJ 5312: 冒险
    Codeforces Round #520 (Div. 2) Solution
  • 原文地址:https://www.cnblogs.com/CIreland/p/9881321.html
Copyright © 2011-2022 走看看