超详细汇编指令

汇编知识

摘录

通用寄存器及标志寄存器

1 通用寄存器:

寄存器是学习汇编知识时的第一课,常用寄存器如下:

AX/EAX  BX/EBX  CX/ECX  DX/EDX  是通用的数据寄存器 用于暂时存放计算过程中的操作数结果 或者其他信息。他们可以分为两个独立的8位寄存器使用,AL/AH BL/BH CL/CH DL/DH,除了通用功能之外还有以下用途:

AX/EAX作为累加器用,是算数运算的主要寄存器,在乘除指令中用来存放操作数,另外,所有的IO指令都是用AX或AL与外部设备传送信息。

BX/EBX在计算存储器地址的时候,可以作为基址寄存器使用。

CX/ECX常用来保存计数值,比如移位指令,循环指令和串处理指令中用作隐含的计数器。

DX在做双字节长运算的时候,可以把DX和AX组合在一起存放一个双字长数,DX存放高16位数据,对于某些IO操作,DX还常常存放IO的端口地址。

SP/ESP  BP/EBP  SI/ESI  DI/EDI四个16/32位寄存器可以像数据寄存器一样在运算过程中存放操作数,但是他们只能以字(16/32位)为单位来使用,他们的主要用途是在存储器寻址时,提供偏移地址,因此他们可称为指针或变址寄存器。

SP/ESP称为堆栈指针寄存器,用来指出栈顶的偏移地址。

BP/EBP称为基址指针寄存器,用来在寻址的时候作为基地址存放的地方,但他必须和堆栈段寄存器SS联用来确定堆栈段中的存储单元地址。

2 标志寄存器

条件码标志是用来记录程序中运行结果的状态信息,他们是根据有关指令的运行结果由CPU自动设置的,由于这些状态信息往往作为后续条件转移指令的转移控制条件,所以称为条件码。

1 进位标志        CF    记录运算时最高有效位产生的进位值

2 符号标志        SF    记录运算结果的符号  1表示负数  0表示正数

3 零标志           ZF    运算结果为0时ZF为1 否则为0

4 溢出标志        OF    在运算中如操作数超出了机器可表示数的范围称为溢出 溢出时为1 否则为0

5 辅助进位标志  AF     记录运算时第3位产生的进位值

6 奇偶标志        PF     用来为机器中传送信息时可能产生的代码出错情况提供检验条件,当结果操作数中1的个数为偶数时置1 否则为0

 

常用指令(传送 交换 取地址 取段 栈操作)

先写几个英文简写及含义。

reg - 寄存器

mem- 内存

lmm - 立即数

1. 传送指令MOV  reg/mem reg/mem/lmm

传送指令,相当于高级语言的赋值语句,把源操作数(reg/mem/lmm)传送到前面的寄存器和内存地址中。

2. 传送填充指令MOVSX/MOVZX reg/mem reg/mem/lmm

传送填充指令,和MOV语句具有相同功能的基础上,对目的操作数的高位进行填充,又分为符号填充(MOVSX)和零(MOVZX)填充。

 (1)符号填充指令:MOVSX

   用源操作数的符号位填充目的操作数的高位数据位。

   比如AL = 87H,则MOVSX CX AL指令执行之后 CX就是0FF87H

 (2)零填充指令:MOVZX

   用0来填充目的操作数的高位数据位。

   比如AL = 87H,则MOVZX CX AL指令执行之后 CX就是0087H

3. 交换指令XCHG reg/mem reg/mem

交换指令XCHG是交换两个寄存器,寄存器和内存变量之间内容的指令,两个操作数的数据类型要相同。

4. 取有效地址指令LEA reg mem

是把一个内存变量的有效地址传送到寄存器中

5. 取段寄存器指令LDS/LES/LFS/LGS/LSS reg mem

LDS是把内存单元的一个“低字”传送到指定的寄存器,并把“高字”传送到段寄存器DS中。

LES,LFS,LGS,LSS是把高字传送到相应的段寄存器ES,FS,GS,SS中。

6. 栈操作指令

 栈的实质是一块内存空间,栈的标准访问形式不同于一般的内存访问形式(用内存地址去访问),而是通过入栈(压栈)与出栈(弹栈)指令进行访问,且栈是后进先出的。(也可以用内存地址的形式去访问栈中的内容,但这属于特殊手段),以下就是栈操作指令

(1) 压栈指令:PUSH, PUSHA, PUSHAD

 - PUSH reg/mem: 把寄存器和内存单元中的值压入栈中

 - PUSHA: 依次把AX,CX,DX,BX,SP,BP,SI,DI等压入栈中

 - PUSHAD: 依次把EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI等压入栈中

(2) 弹栈指令:POP, POPA, POPAD

 - POP reg/mem: 弹出栈首的值到指定的寄存器和内存单元中

 - POPA: 把栈中的值依次弹到DI,SI,BP,SP,BX,DX,CX,AX等寄存器中

 - POPAD: 把栈中的值依次弹到EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX等寄存器中

压栈与弹栈的补充说明:

ESP/SP寄存器始终指向栈首,所以在PUSH时,SP=SP-2或4, *SP = 操作数(C语法,就是SP寄存器先向前移动两位和四位,然后将值写入指向的内存区域),POP一个项的时候,操作数 = *SP, SP = SP+ 2或4

在16位操作系统使用SP,AX等寄存器,在32位操作系统则应该使用ESP,EAX系列的寄存器,在64位操作系统则可以使用RSP寄存器。

VC++编译器生成的汇编代码使用栈的时候,并不是按标准做法PUSH和POP,而是PUSH多个项目后,用ESP做为基址,向后偏移四位来寻找第二个项,直到访问结束后一次性的把栈清空,这样省略了多次弹栈。

 

 

算术运算指令

算术运算指令是反映CPU运算能力的指令,也是编程时候最常用到的一组指令,包括加减乘除以及相关的辅助指令。

该组指令的操作数可以是8位,16位,32位(80386+),当存储单元是该类指令的操作数的时候,该操作数的寻址方式可以是任何一种存储单元的寻址方式。

1. 加法指令

ADD reg/mem, reg/mem/imm  - 加法指令

受影响的标志位:AF CF OF PF SF ZF

功能:把源操作数的值加到目标操作数

INC reg/mem

受影响的标志位:AF、OF、PF、SF和ZF,不影响CF

功能:把操作数的值+1

ADC reg/mem, reg/mem/imm - 带进位加指令(较少使用)

受影响的标志位:AF CF OF PF SF ZF

功能:把源操作数和进位标志位CF的值一起加到目的操作数中

XADD reg/mem reg(较少使用)

受影响的标志位:AF CF OF PF SF ZF

功能:先交换两个操作数 然后执行加法运算

以上指令的ADC和XADD在标准VC++编译后的汇编代码中不出现。

2. 减法指令

SUB reg/mem reg/mem/imm

受影响的标志位:AF CF OF PF SF ZF

功能:把源操作数的值减去目的操作数

DEC reg/mem

受影响的标志位:AF、OF、PF、SF和ZF,不影响CF

功能:把操作数的值-1

SBB reg/mem reg/mem/imm

受影响的标志位:AF CF OF PF SF ZF

功能:把源操作数和进位标志位CF的值从目的操作数一起减去

NEG reg/mem

受影响的标志位:AF CF OF PF SF ZF

功能: 操作数 = 0 - 操作数, 改变操作数的正负号。

3. 乘法指令

计算机的乘法指令分为无符号指令和有符号指令两种,他们的区别在于:数值的最高位是做为“数值”参与运算还是做为“符号”参与运算。

乘法指令的被乘数都是做为隐含操作数,乘数在指令中显示的写出来,CPU会根据乘数是8位,16位,32位来自动选用被乘数:AL,AX或EAX。指令的功能是把显示操作数和隐含操作数相乘,并把乘积存入AL,AX或EAX中。(现在的80386+一般都是用EAX做为被乘数)

MUL/FMUL reg/mem - 无符号整数/浮点数乘法指令

受影响的标志位:CF和OF

功能:把显示操作数和隐含操作数都做为无符号数相乘。比如MUL 5就是eax = eax * 5

IMUL/FIMUL reg/mem - 有符号整数/浮点数乘法指令

IMUL/FIMUL reg, imm

IMUL/FIMUL reg,mem

功能:把两个操作数做为有符号数相乘。

4. 除法指令

DIV,无符号数的除法指令,和8086一样, 指令给出一个操作数,被除数已默认。如果指令中给出的操作数为32位,那么被除数将是EDX:EAX,最终的商将存放在EAX, 余数将存放在EDX中。如果指令给出操作数为16位,那么被除数为EAX,最终得到的商放在AX,余数放在EAX的高16位。如果指令中给出的操作数为8 位,那么被除数是16位,最终得到的商将放在AL中,余数放在AH中。

IDIV,有符号数的除法指令,用法和8086相同,不过支持32位操作

逻辑运算指令

逻辑运算指令是另外一组重要的常用指令,包括逻辑与AND,逻辑或OR,逻辑非NOT,和异或指令XOR。

1. AND reg/mem, reg/mem/imm - 逻辑与指令

受影响的标志位:CF,OF,PF,SF,ZF

功能:把源操作数和目的操作数进行二进制位的与操作,结果存入源操作数中。

2. OR reg/mem, reg/mem/imm - 逻辑或指令

受影响的标志位:CF,OF,PF,SF,ZF

功能:把源操作数和目的操作数进行二进制位的或操作,结果存入源操作数中。

3. NOT reg/mem

不影响任何标志位

功能:把操作数的每个二进制位取反

4. XOR reg/mem, reg/mem/imm

受影响的标志位CF,OF,PF,SF,ZF

功能:把源操作数和目的操作数进行每个二进制位的异或操作,结果存入源操作数中。

 

跳转指令及循环指令

1. TEST reg/mem, reg/mem/imm - 检测位指令

受影响标志位:CF(0),OF(0),PF,SF和ZF

功能:检测位指令会将源操作数和目标操作数进行逻辑与操作,根据运算结果设置标志位,但是并不保存运算结果到源操作数,只是设置标志位。该指令执行后通常是一条JE,JNE,JZ或JNZ等条件转移指令。

2. 循环指令

循环指令的执行本身并不影响任何标志位,以CX或ECX做为计数器。

LOOP/LOOPW/LOOPD 标号

LOOP: 在实地址模式下使用CX寄存器而不是ECX寄存器。

LOOPW:在任何模式下都会使用CX寄存器作为计数器。

LOOPD:在任何模式下都会使用ECX寄存器作为计数器。

3. 转移指令

转移指令是汇编语言程序员经常使用的一组指令。在高级语言中,时常有“尽量不要使用转移语句”的劝告,但如果在汇编语言的程序中也尽量 不用转移语句,那么该程序要么无法编写,要么没有多少功能,所以,在汇编语言中,不但要使用转移指令,而且还要灵活运用,因为指令系统中有大量的转移指令。

转移指令分无条件转移指令和有条件转移指令两大类。

无条件转移指令:包括JMP指令,子程序的调用和返回,中断的调用和返回。

JMP 标号/reg/mem

JMP指令是从程序当前执行的地方无条件转移到另外一个地方执行,这种执行可以是一个短(short)转移(偏移量在-128到127范围内),近(near)转移(偏移量在正负32K范围内),或者远(FAR)转移(在不同的代码段内跳转。)

短转移和近转移只是代码段内的转移,仅仅需要把偏移量入栈,远转移需要把要跳转的代码段的地址和偏移量入栈。

转移指令本身不影响标志位。

 

子程序的定义 调用及返回

1. 子程序的定义

如同C语言一样,汇编语言也具备结构化的能力。

首先说子程序的定义格式:

子程序名 PROC [NEAR | FAR] 

… ;子程序体 

子程序名 ENDP 

PROC和ENDP是子程序的首尾标识,子程序名必须是相同的,子程序可以分为NEAR近调用和FAR远调用,所谓近调用就是只能在同一段内的其他程序调用,而远待用可以被不同段的程序调用。

2. 子程序的调用

所以,根据NEAR和FAR,也有相应的调用方式,NEAR的子程序调用的时候只需要把偏移量压栈即可,FAR的子程序要把段地址和偏移量压栈(分别压入CS和IP寄存器),然后即可调用。

调用的方式:

 

CALL  DISPLAY

 

;DISPLAY是子程序名

 

CALL  BX

 

;BX的内容是子程序的偏移量

 

CALL  WORD1

 

;WORD1是内存字变量,其值是子程序的偏移量

 

CALL  DWORD1

 

;DWORD1是双字变量,其值是子程序的偏移量和段值

 

CALL  word ptr [BX]

 

;BX所指内存字单元的值是子程序的偏移量

 

CALL  dword ptr [BX]

 

;BX所指内存双字单元的值是子程序的偏移量和段值

 

3. 子程序的返回

当子程序执行完了之后,需要返回到主调指令上下文中,并不像跳转指令那样不会返回,为了实现这个功能,指令系统提供了一条专用指令RET.

RET/RETN/RETF [imm]

子程序的返回在功能上来说是子程序的调用的逆操作,为了与子程序的远/近调用相对应,子程序的返回也分为远返回和近返回。

返回指令在堆栈方面是调用指令的逆操作。

在近类型的子程序中,返回指令RET是近返回,功能是把栈顶的值弹出到指令指针寄存器IP中,SP会被加2。

在远类型的子程序中,返回指令RET是远返回,功能是:先弹出栈顶的值到IP中,再弹出栈顶的值到CS中,SP总共向后移动了4位(当然80386+的CPU是ESP向后移动了两个四位)

如果返回指令后面加入了立即数,那么表示返回地址之后,SP还要增加的偏移量。并不是高级语言中return的值。

在masm5.0+的环境中可以直接使用RETN和RETF来显示告诉编译器本子程序是近返回还是远返回。

 

 

 

RET

 

;可能是近返回,也可能是远返回

 

RETN

 

;近返回指令

 

RETF

 

;远返回指令

 

RET 6

 

;子程序返回后,(SP)←(SP) + 6

 

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值