计算机系统基础 6 常用机器指令

数据传输指令

  • 一般数据传送指令:MOV(数据传送)、MOVSX(有符号扩展传送)、MOVZX(无符号扩展传送)
  • 堆栈操作指令:PUSH、POP、PUSHA、PUSHAD、POPA、POPAD
  • 标志寄存器操作指令:PUSHF、POPF、PUSHFD、POPFD、LAHF、SAHF 
  • 地址传送指令:LEA 
  • 待条件的数据传送指令:CMOVE、CMOVNE、CMOVA ….

一般数据传送指令

  1. MOV        OPD,  OPS          :数据传送
  2. MOVSX   R16/R32,  OPS    :符号扩展传送
  3. MOVZX   R16/R32, OPS     :0(无符号)扩展传送
 int      x = 10;
 short  y = 20;
 x = y;
 movsx      eax, word ptr [ebp-14h]  
 mov          dword ptr [ebp-8], eax  

 unsigned short  z = 20;
 mov         eax,14h  
 mov         word ptr [ebp-20h],ax  
 x = z;
 movzx     eax, word ptr [ebp-20h]  
 mov         dword ptr [ebp-8], eax 

使用单个标志位判断转移条件是否成立

        cmove/cmovz、cmovc、cmovs、cmovo、cmovp

条件:ZF=1                 CF=1         SF=1      OF=1     PF=1 

        cmovne/cmovnz、cmovnc、cmovns、cmovno、cmovnp

条件:ZF=0                     CF=0           SF=0       OF=0        PF=0

使用多个标志位组合判断转移条件是否成立

        cmova、cmovb、cmovg、cmovl、cmovae、cmovbe、cmovge、cmovle

  1. cmova:如果无符号溢出标志 CF 为 0,则将源操作数传送到目的操作数。即 "COnditional MOver if Above" 的缩写。

  2. cmovb:如果进位标志 CF 为 1,则将源操作数传送到目的操作数。即 "COnditional MOver if Below" 的缩写。

  3. cmovg:如果大于标志 ZF=0 and SF=OF,则将源操作数传送到目的操作数。即 "COnditional MOver if Greater" 的缩写。

  4. cmovl:如果小于标志 SF ≠ OF,则将源操作数传送到目的操作数。即 "COnditional MOver if Less" 的缩写。

  5. cmovae:如果无符号大于或等于标志 CF=0,则将源操作数传送到目的操作数。即 "COnditional MOver if Above or Equal" 的缩写。

  6. cmovbe:如果小于或等于标志 CF=1 or ZF=1,则将源操作数传送到目的操作数。即 "COnditional MOver if Below or Equal" 的缩写。

  7. cmovge:如果大于等于标志 SF=OF,则将源操作数传送到目的操作数。即 "COnditional MOver if Greater or Equal" 的缩写。

  8. cmovle:如果小于或等于标志 ZF=1 or SF ≠ OF,则将源操作数传送到目的操作数。即 "COnditional MOver if Less or Equal" 的缩写。

  • cmovg 适用于有符号整数的比较,而 cmova 适用于无符号整数的比较。

//设无符号双字类型变量 x、y、z,将x和y中间的大者存放到z中
     mov   eax, x
     cmp   eax, y  ; //比较指令,
                   ;//根据(eax)-(y) 设置标志位
     jae    L1
     mov    eax, y
L1:  mov    z,   eax
     cmovb   eax, y  ; CF=1 且 ZF=0时,传送
     mov     z, eax
   int  x,y,z;
   z = x > y ? x : y;
   mov	ecx, DWORD PTR _y$[ebp]
   add	esp, 16	; 00000010H
   cmp	DWORD PTR _x$[ebp], ecx
   cmovg	ecx, DWORD PTR _x$[ebp]
/*
下面使用 z 时直接使用了 ecx
Release 版,不同程序编译结果不同
_x$、_y$是编译时生成的符号常量:_x$ = …  _y$ = …
红色语句与z的赋值无关,是下一条C语句翻译结果的部分。将其穿插到前面提高流水线的处理性能。
*/

堆栈操作指令 

        进栈指令: PUSH   OPS

字数据入栈

  • (ESP) – 2  →  ESP
  • 字数据 → [ESP]

双字数据入栈: 

  • (ESP) – 4  →  ESP
  • 双字数据 → [ESP]

        出栈指令: POP  OPD 

字数据出栈

①  ([ESP]) → OPD

②  (ESP)+2 → ESP

记为:↑(ESP) → OPD

双字数据出栈类似, (ESP)+4->ESP

  •         8个16位寄存器入栈    PUSHA 
  •         8个16位寄存器出栈    POPA 
  •         8个32位寄存器入栈    PUSHAD 
  •         8个32位寄存器出栈    POPAD 

        32位标志寄存器进栈指令:

  •         格式:PUSHFD
  •         功能:将标志寄存器的内容压入堆栈,
  •         记为(eflags)→↓(esp)。

        32位标志寄存器出栈指令:

  •         格式:POPFD
  •         功能:将栈顶内容弹出送入标志寄存器中,
  •         记为↑(esp)→eflags。        

        16位标志寄存器进栈指令:

  •         格式:PUSHF
  •         功能:将标志寄存器的内容压入堆栈,
  •         记为(eflags)15-0→↓(esp)。

        16位标志寄存器出栈指令 

  •         格式:POPF
  •         功能:将栈顶内容弹出送入标志寄存器中,
  •         记为↑(esp)→eflags 15-0 。

地址传送指令 

         传送偏移地址指令

                语句格式:LEA  R32,  M32

                功        能:将M32 对应的地址送入R32中。

               与MOV对比,如果是mov ebx, [eax]会取出eax的内容所指向的内存的值,而LEA会将EAX的内容视作地址传送。 

LEA    ESI,  NUM

LEA    EDI,  [ESI+4]        (ESI)+4 ➡ EDI          

实现EAX)+ (EBX) * 8 ➡ ECX  :LEA   ECX,[EAX + EBX * 8]

总结

一般传送            MOV     OPD,OPS

有符号数传送     MOVSX   R16/R32,OPS/非立即数

无符号数传送     MOVZX   R16/R32, OPS/非立即数

传送偏移地址     LEA     R32, M32

进栈                   PUSH    OPS

出栈                   POP     OPD

32位通用寄存进栈、出栈   PUSHADPOPAD

标志寄存器进栈、出栈     PUSHFDPOPFD

LEA(Load Effective Address)和 MOV(Move)是 x86 汇编语言中的两种指令,它们虽然都可以用于数据的传输,但在功能和用途上有明显的区别。

  1. MOV 指令

    • MOV 指令用于将数据从一个位置复制到另一个位置。
    • 示例:
      MOV AX, [BX] ; 将内存地址 BX 处的数据复制到寄存器 AX 中 
      MOV [DI], CX ; 将寄存器 CX 中的数据复制到内存地址 DI 处
    • MOV 指令的作用是将数据从一个位置复制到另一个位置,可以是寄存器之间的传输,也可以是寄存器与内存之间的传输,或者是内存之间的传输。它是一种通用的数据传输指令。
  2. LEA 指令

    • LEA 指令用于加载有效地址,即将内存地址计算结果加载到目标寄存器中,而不是将内存中的数据加载到寄存器中。
    • 示例:
      LEA SI, [BX+DI] ; 将 BX 和 DI 寄存器中的值相加得到地址,加载到 SI 寄存器中 
      LEA BX, [SI+10] ; 将 SI 寄存器中的值加上 10 得到地址,加载到 BX 寄存器中
    • LEA 指令的作用是将有效地址加载到寄存器中,这个地址是根据指定的内存地址计算得到的,而不是实际存储的数据。LEA 指令通常用于进行地址计算,而不是数据传输。

        总的来说,MOV 指令用于数据的传输,而 LEA 指令用于计算地址。虽然它们都涉及到寄存器和内存之间的操作,但是 MOV 是用于数据传输,而 LEA 则是用于地址计算。

 

算术运算指令 

  1. 加法指令: INC、ADD、ADC
  2. 减法指令:  DEC、NEG、SUB、SBB、CMP
  3. 乘法指令:  IMUL、MUL
  4. 除法指令:  IDIV、DIV
  5. 符号扩展指令:  CBW、CWD、CWDE、CDQ

 一般对标志位都有影响,但INCDECCF无影响 

加法指令

        加1指令INC   OPD      ; (OPD) +1 → OPD

        加指令:ADD  OPD,OPS   ; (OPD)+(OPS) → OPD

        带进位加指令:

                语句格式:ADC  OPD,OPS

                功能:       (OPD) + (OPS) + CF → OPD

减法指令 

        减1指令:DEC  OPD  ;  (OPD) –1 → OPD

        求补指令:NEG  OPD ; (OPD)求反加1 → OPD

        减指令SUB  OPD,OPS  ;(OPD)-(OPS) → OPD 

        带借位减指令:SBB  OPD,OPS;(OPD) – (OPS) – CF → OPD

乘法指令 

        有符号乘法      

                双操作数的有符号乘指令:

  •                 语句格式:IMUL  OPD, OPS
  •                 功        能:(OPD) * (OPS) → OPD

                3个操作数的有符号乘指令:

  •                 语句格式:IMUL  OPD, OPS,n
  •                 功        能:(OPS) * n → OPD

                单操作数的有符号乘法 

                语句格式: IMUL   OPS

  •                 字节乘法: (AL) * (OPS) → AX
  •                 字  乘  法: (AX) * (OPS) → DX , AX 
  •                 双字乘法:(EAX) * (OPS) →EDX, EAX 

         无符号乘法 

        语句格式: MUL   OPS

        功        能:

  •         字节乘法:  (AL) * (OPS) → AX
  •         字乘法:      (AX) * (OPS) → DX , AX
  •         双字乘法:(EAX) * (OPS) →EDX, EAX

除法指令 

        有符号除法

        IDIV   OPS

  •         字节除法:(AX) / (OPS) → AL(商),AH(余)
  •         字  除  法:(DX, AX) / (OPS) → AX (商), DX (余)
  •         双字除法:(EDX, EAX) / (OPS) → EAX (商), EDX

        无符号除法

        DIV   OPS

  •         字节除法:(AX) / (OPS) → AL(商), AH(余)
  •         字  除  法:(DX, AX) / (OPS) → AX (商), DX (余)
  •         双字除法:(EDX, EAX) / (OPS) → EAX (商), EDX

使用除法指令应注意的问题

(1) 除数为 0
(2) 除法溢出

      (AX) = 1234, (BL)=1,  (AX) / (BL) → AL

        为了解决这种情况,需要考虑极端,也就是用来存储商的寄存器大小要等于被除数的长度,即比如这里就需要用AX来存商、DX来存余数,所以要将被除数和除数扩展到(EAX)和(BX)中。

符号扩展指令 

        将字节转换成字

                CBW:将AL中的符号扩展至AH中。

        将字转换成双字

                CWD:将AX中的符号扩展至DX中。

        将AX中的有符号数扩展为32位送EAX:CWDE

        将EAX中的有符号数扩展为64位数送  EDX,EAX:CDQ

unsigned short us1,us2;
unsigned int ui;
short s1,s2 ;
int i;

us1 = ui / us2;
00EF1975  movzx     ecx,word ptr [ebp-18h]  
00EF1979  mov         eax,dword ptr [ebp-24h]  
00EF197C  xor          edx,edx  
00EF197E  div          eax,ecx  
00EF1980  mov         word ptr [ebp-0Ch],ax  
s1 = i / s2;
00EF1984  movsx     ecx,word ptr [ebp-3Ch]  
00EF1988  mov         eax,dword ptr [ebp-48h]  
00EF198B  cdq  
00EF198C  idiv         eax,ecx  
00EF198E  mov        word ptr [ebp-30h],ax ;这里只取ax是因为要赋给short型的s1

正确理解  div eax, ecx:本质是 (edx, eax) / (ecx)         

位运算指令 

  • 求反:NOT    OPD            ; ~ (OPD) →OPD
  • 逻辑乘:AND   OPD, OPS   ; (OPD) & (OPS) →OPD
  • 测试指令:TEST  OPD, OPS   ; (OPD) & (OPS) 
  • 逻辑加:OR      OPD, OPS   ; (OPD) | (OPS) →OPD
  • 按位加XOR   OPD, OPS   ; (OPD) ^ (OPS) →OPD

移位指令 

(1)算术左移 SAL    Shift Arithmetic Left
(2)逻辑左移 SHL    SHift Logical  Left
( 两种左移实际上完全一样 )
(3)逻辑右移 SHR    SHift Logical  Right
(4)算术右移 SAR    Shift Arithmetic Right

Debug版本与Release版本的对比

例子1

 int   x, y;
 y = x * 9;
 imul     eax, dword ptr [x], 9  
 mov      dword ptr [y], eax
//Debug version
mov      ecx, dword ptr [x]  
lea        eax, [ecx+ecx*8]
mov      dword ptr [y], ecx
//Release version

 例子2

 int   x, y;
 y = x * 17;
 imul        eax, dword ptr [x], 11h  
 mov         dword ptr [y], eax
//Debug version
 mov        ecx, dword ptr [x]  
 mov        eax, ecx  
 shl          eax, 4  
 add         eax, ecx
 mov       dword ptr [y], eax
//Release version

位运算应用 

编写C程序,判断两个整数是否相等,相等为1,不相等为 0

int  isEqual(int x, int y) {
      return  !(x ^ y);

      //   return  x==y; 
}

编写C程序,实现用按位运算方法实现计算 -x

 -x      等于    ~x+1   

NOT   x

INC    x

用乘法指令实现          MOV   EAX,x

                                    IMUL   EAX, -1

                                    MOV   x,   EAX

用减法指令实现           MOV   EAX,0

                                    SUB    EAX,  x

                                    MOV   x,   EAX

试用不同指令将(AX)0

MOV   AX,  0

SUB     AX,  AX

AND    AX,  0

XOR    AX, AX

SHL     AX, 16

试用不同的指令,将AX的高、低字节内容互换。

XCHG  AH, AL(交换 AH 和 AL 寄存器中的内容。

ROL     AX,  8(将 AX 寄存器中的值向左循环移动 8 位

ROR     AX, 8(将 AX 寄存器中的值向右循环移动 8 位

只使用位运算、算术运算等指令,不使用转移之类的语句,实现求一个数的绝对值

int abs_op(int x){

    int y,mask;

    mask = x >> 31;  //算术右移,得到FFFFFFFF/00000000

    y = (x ^ mask) + ~mask + 1 ;     //method 1:

    y = (x ^ mask) + (1-mask) - 1;   //method 2

    y = ((x & 0x80000000) >> 31) + (x ^ mask); //method 3

    return y;

}

//注意运算的优先级

//单纯的 x >> 31 是算术右移

//x & 0x80000000>> 31 是逻辑右移

不使用转移之类的语句,判断两个有符号数相加 是否出现溢出。

int addOK(int x, int y)

   int sum = x + y; 

   int x_neg = x >> 31; 

   int y_neg = y >> 31; 

   int s_neg = sum >> 31; 

/* Overflow when x and y have same sign, but s is different */ 

    return !(~(x_neg ^ y_neg) & (x_neg ^ s_neg));

}

复杂指令集和精简指令集

按指令格式的复杂度来分,有两种类型计算机:

  •         复杂指令集计算机 CISC (Complex Instruction Set Computer)

早期CISC设计风格的主要特点

         (1) 指令系统复杂
              变长操作码 / 变长指令字 / 指令多 / 寻址方式多 / 指令格式多
         (2) 指令周期长
               绝大多数指令需要多个时钟周期才能完成
         (3) 各种指令都能访问存储器
               除了专门的存储器读写指令外,运算指令也能访问存储器
         (4) 采用微程序控制
         (5) 难以进行编译优化来生成高效目标代码
CISC的缺陷
日趋庞大的指令系统使计算机的研制周期变长,
难以保证设计的正确性,难以调试和维护,
因指令操作复杂而增加机器周期,从而降低了系统性能。
  •         精简指令集计算机 RISC (Reduce Instruction Set Computer)
 (1) 简化的指令系统

指令少 / 寻址方式少 / 指令格式少 / 指令长度一致

 (2) 以RR方式工作

除Load/Store指令可访存外,其余指令都只访问寄存器

 (3) 指令周期短

以流水线方式工作, 因而除Load/Store指令外,其他简单指令都只需一个或一个不到的时钟周期就可完成

  (4) 采用大量通用寄存器,以减少访存次数
  (5) 采用硬连线路控制器,不用或少用微程序控制
  (6) 采用优化的编译系统,力求有效地支持高级语言程序
​​​​​​​

MIPS是典型的RISC处理器,82年以来新的指令集大多采用RISC体系结构x86 因为“兼容”的需要,保留了CISC的风格,同时也借鉴了RISC思想

Microcomputer without interlocked pipeline stages

对CISC进行测试,发现一个事实:
        程序中各种指令出现的频率悬殊很大,最常使用的是一些简单指令,这些指令占程序的80%,但只占指令系统的20%。
        在微程序控制的计算机中,占指令总数20%的复杂指令占用了控制存储器容量的80%。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值