常用命令 与 其他注释

First Post:

Last Update:

因为网上各种各样的笔记都不如自己写一遍来得方便查阅,所以按照自己的喜好整理一下汇编的笔记。目前跟着Kip Irvine的书才学到第六章(条件跳转),所以再之后的笔记暂时保留,等之后学完了再整理吧。

部分表格来源于:

https://blog.csdn.net/qq_36982160/article/details/82950848

插图ID:87882344

常用的寄存器:

31———-16

15—8

7—-0

16位

32位

AH

AL

AX

EAX

BH

BL

BX

EBX

CH

CL

CX

ECX

DH

DL

DX

EDX

BP

EBP

SI

ESI

DI

EDI

SP

ESP

注:在VisualStudio还能看见EFL与EIP两种寄存器

EAX:拓展累加器。常用于做累加器、取返回值等操作。

EBX:基底暂存器。

ECX:计数暂存器。

EDX:资料暂存器。

ESI:拓展源变址寄存器。

EDI:拓展目的变址寄存器。

ESP:拓展帧指针寄存器,也叫栈指针寄存器(extended stack pointer),存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶(我将其当作一个指向当前调用处的栈指针)

EBP:基址指针寄存器(extended base pointer),存放着一个指针,该指针永远指向系统栈最上面一个栈帧的底部(我将其当作一个指向当前过程的起始栈址的栈指针)

EFL:EFLAGS寄存器。包含了独立的二进制位(状态标志位),用于控制CPU操作或反应CPU的结果。

EIP:指令指针。存放下一条将要指向的指令的地址。

状态标志位:

CF进位标志位

主要反映算术运算是否产生进位或借位,若产生,则CF=1,否则CF=0

OF溢出标志位

反映有符号数运算结果是否产生溢出,是置1,否置0

SF符号标志位

根据运算结果的最高位,若最高位为1则SF为1,否则为0,反映了有符号数运算结果的正负(0正1负)

ZF零标志位

反映运算结果是否为0

AC辅助进位标志位

AF=1时,向高位或高字节进位或借位

PF奇偶校验标志位

运算结果操作数位为1的个数为偶数个时为1,否则为0.

对应EFL寄存器中的顺序。

不过,有的集成开发环境里对状态标志位的写法是不一样的,下图为为别名(其实也不能称为别名,但姑且这么形容比较方便吧)。

状态标志操作指令

指令

中文名

格式

解释

CLC(clear carry flag)

清进位标志指令

CLC

使进位标志CF为0

STC(set carry flag)

置进位标志指令

STC

使进位标志CF为1

CMC(complement carry flag)

进位标志取反指令

CMC

使进位标志CF取反

LAHF(load status flags into AH register)

获取状态标志操作指令

LAHF

把位于标志寄存器低端的5个状态标志位(p26图2.3)信息同时送到寄存器AH的对应位

SAHF(store AH into Flags)

设置状态标志操作指令

SAHF

对标志寄存器中的低8位产生影响,使得状态标志位SF、ZF、AF、PF和CF分别成为来自寄存器AH中对应位的值,但保留位(位1、位3、位5)不受影响

数据类型:

类型

用法

BYTE

8位无符号整数,B代表字节

SBYTE

8位有符号整数,S代表有符号

WORD

16位无符号整数

SWORD

16位有符号整数

DWORD

32位无符号整数,D代表双(字)

SDWORD

32位有符号整数

FWORD

48位整数(保护模式下的远指针)

QWORD

64位整数,Q代表四(字)

TBYTE

80位整数,T代表10字节

REAL4

32位IEEE短实数(4字节)

REAL8

64位IEEE长实数(8字节)

REAL10

80位IEEE拓展实数(10字节)

伪指令:

指令

作用

“=”

可将立即数与标记划等号,在调用标记时将直接进行替代

“$”

当前地址计数器。直接代表了当前位置的地址偏移量

DUP

可直接为数据分配空间。例:BYTE 20 DUP(0) 分配20字节

EQU

将符号名称与整数表达式或任意文本相连(类似于”=”,但更偏向于定义赋值,区别在于不可重定义)

TEXTEQU

创建文本宏。分配文本/textmacro分别文本宏内容/%constExpr分配整数常量

关于汇编的伪指令其实还有很多,诸如 .break/.else/.if等等形如C语言中的操作,也支持”=>”/“==”等判断符。

简单传送指令

指令

中文名

格式

解释

备注

MOV

传送指令

MOV DEST,SRC

DEST<=SRC

XCHG

交换指令

XCHG OPER1,OPER2

把操作数oper1的内容与操作数oper2的内容交换

oper1和oper2可以是通用寄存器或存储单元,但不能同时是操作单元,也不能是立即数。

拓展传送指令

指令

中文名

格式

解释

备注

MOVSX

符号拓展传送指令

MOVSX DEST,SRC

把源操作数SRC符号拓展后送至目的操作数DEST

src可以是通用寄存器或者存储单元,但是dest只能是通用寄存器(零拓展传送指令不会改变源操作数,也不影响标志寄存器的状态)

MOVZX

MOVZX DEST,SRC

把源操作数SRC零拓展后送至目的操作数DEST

零拓展传送指令不会改变源操作数,也不影响标志寄存器的状态

简单加减指令

指令

中文名

格式

解释

备注

ADD

加法指令

ADD DEST,SRC

DEST<=DEST SRC

两数相加,结果于前

SUB

减法指令

SUB DEST,SRC

DEST<=DEST-SRC

两数相减,结果于前

INC

加1指令

INC DEST

DEST<=DEST 1

DEC

减1指令

DEC DEST

DEST<=DEST-1

NEG

取补指令

NEG OPRD

OPRD=0-OPRD

对操作数取补(相反数)

常用条件转移指令

指令

中文名

格式

解释

备注

CMP

比较指令

CMP DEST,SRC

根据dest-src的差影响各状态标志寄存器

不把dest-src的结果送入dest

JMP

无条件段内直接转移指令

JMP LABEL

使控制无条件地转移到标号为label的位置

无条件转移指令本身不影响标志

堆栈和堆栈操作

指令

中文名

格式

解释

备注

PUSH

进栈指令

PUSH SRC

把源操作数src压入堆栈

源操作数src可以是32位通用寄存器、16位通用寄存器和段寄存器,也可以是双字存储单元或者字符存储单元,还可以是立即数

POP

出栈指令

POP DEST

从栈顶弹出一个双字或字数据到目的操作数

如果目的操作数是双字的,那么就从栈顶弹出一个双字数据,否则,从栈顶弹出一个字数据,出栈至少弹出一个字(16位)该指令弹出ESP处数据

PUSHA

16位通用寄存器全进栈指令

PUSHA

将所有8个16位通用寄存器的内容压入堆栈

压入顺序是AX CX DX BX SP BP SI DI,然后对战指针寄存器SP的值减16,所以SP进栈的内容是PUSHA指令执行之前的值

POPA

16位通用寄存器全出栈指令

POPA

以PUSHA相反的顺序从堆栈中弹出内容,从而恢复PUSHA之前的寄存器状态

SP的值不是由堆栈弹出的,而是通过增加16来恢复

PUSHAD

32位通用寄存器全进栈指令

PUSHAD

将所有8个32位通用寄存器的内容压入堆栈

压入顺序是EAX ECX EDX EBX ESP EBP ESI EDI,然后对栈指针寄存器ESP的值减32,所以SP进栈的内容是PUSHAD指令执行之前的值

POPAD

32位通用寄存器全出栈指令

POPAD

以PUSHAD相反的顺序从堆栈中弹出内容,从而恢复PUSHAD之前的寄存器状态

ESP的值不是由堆栈弹出的,而是通过增加32来恢复

过程调用和返回指令

指令

中文名

格式

解释

备注

CALL

过程调用指令

CALL LABEL

段内直接调用LABEL

与jmp的区别在于call指令会在调用label之前保存返回地址(call 中return之后主程序还可以继续执行,jmp 当label执行完毕后不能返回主程序继续执行)

RET

段内过程返回指令

RET

使子程序结束,继续执行主程序

ret 4;ret 8等分别标识返回后回退的栈帧大小

逻辑运算指令

指令

中文名

格式

解释

备注

NOT

否运算指令

NOT OPRD

把操作数OPRD按位取反,然后送回OPRD

AND

与运算指令

AND DEST,SRC

把两个操作数进行与运算之后结果送回DEST

同1得1,否则得0

OR

或运算指令

OR DEST,SRC

把两个操作数进行或运算之后结果送回DEST

同0得0,否则得1

XOR

异或运算

XOR DEST,SRC

把两个操作数进行异或运算之后结果送回DEST

相同得0不同得1

TEST

测试指令

TEST DEST,SRC

与AND指令类似,将各位相与,但是结果不送回DEST,仅影响状态位标志,指令执行后,ZF、PF、SF反映运算结果,CF和OF被清零

通常用于检测某些位是否为1,但又不希望改变操作数的值

循环指令

指令

中文名

格式

解释

备注

LOOP

计数循环指令

LOOP LABEL

使ECX的值减1,当ECX的值不为0的时候跳转至LABEL,否则执行LOOP之后的语句

LOOPE

等于循环指令

LOOPE LABEL

使ECX的值减1,如果结果不等于0并且零标志ZF等于1(表示相等),那么就转移到LABEL,否则执行LOOPE之后的语句

LOOPZ

零循环指令

LOOPZ LABEL

使ECX的值减1,如果结果不等于0并且零标志ZF等于1(表示相等),那么就转移到LABEL,否则执行LOOPZ之后的语句

LOOPNE

不等于循环指令

LOOPE LABEL

使ECX的值减1,如果结果不等于0并且零标志ZF等于0(表示不相等),那么就转移到LABEL,否则执行LOOPNE之后的语句

LOOPNZ

非零循环指令

LOOPNZ LABEL

使ECX的值减1,如果结果不等于0并且零标志ZF等于0(表示不相等),那么9就转移到LABEL,否则执行LOOPNZ之后的语句

JECXZ

计数转移指令

JECXZ LABEL

当寄存器ECX的值为0时转移到LABEL,否则顺序执行

通常在循环开始之前使用该指令,所以循环次数为0时,就可以跳过循环体

LEA:将存储器操作数mem的4位16进制偏移地址送到指定的寄存器。

LEA reg16,mem

ENTER/LEAVE:自动创建栈帧/自动删除栈帧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
MySub PROC
ENTER 8,0
.
.
.
LEAVE
RET
MySub ENDP
;上下两端代码有着相同的意义 编译器将把上面的代码翻译为下面的代码
MySub PROC
push ebp
mov ebp,esp
sub esp,8
.
.
.
mov esp,ebp
pop ebp
ret
MySub ENDP

REP:重复指令。以ECX为计数器。

rep movs dword ptr es:[edi],dword ptr ds:[esi]
意思bai就是将ESI指向的du地址zhi的值以4字节方式拷贝到daoEDI指向的地址中,重复执行ECX次,每次执zhuan行后ESI+4,EDI+4,ECX-1,OD中在这段代码中下断后按F7单步步入就可以观察到这3个寄存器的变化

STOS:是将AL/AX/EAX的值存储到[EDI]指定的内存单元中

STOS BYTE PTR ES:[EDI]       ——BYTE:把al的值放到EDI指定的位置

STOS WORD PTR ES:[EDI]     ——WORD:把ax的值放到EDI的指定位置

STOS DWORD PTR ES:[EDI]  ——DWORD:把EAX的值放到EDI的位置

INVOKE:只用于32位模式,用于将参数入栈(INVOKE procedureName [, arguementList])后者代表入栈的数据,可为列表

PROC:(label PROC [attributes] [USES reglist] ,paramenter_list)

PROTO:64位中用于指定程序的外部过程/32位中可包含参数

如上三者分别可在32位模式下表示:(过程调用——过程实现——过程原型)

汇编语言的常用编辑格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.386;表示为32位程序
.model flat,stdcall;储存形式 声明(内存模式/调用规范)
.stack 4096; 表示分配4096字节空间用于堆栈
ExitProcess PROTO,dwExitCode:DWORD
INCLUDE Irvine32.inc;调用链接库
;分号在汇编中为注释符
.data ;可在下方申请变量
VALL BYTE 20h,30h,40h,50h;数组声明
greet BYTE "hello world",0
BYTE "i want to creat a program",0dh,0ah
byte "so i try to exit this greet ",0dh,0ah,0
;字符串声明

.data? ;同样是声明变量的区域

.code ;程序代码区起始点 标记
main PROC ;程序入口
mov eax,0
mov ebx,5
mov ecx,7
call SumOf

INVOKE ExitProcess,0
main ENDP ;过程的结束
SumOf PROC ;类似于函数,通过call指令调用
add eax,ebx
add eax,ecx
ret
SumOf ENDP
END main ;程序的结束