目录

知识点

知识点

小知识

ptr 强制类型转换

lea 指令可以用来将一个内存地址直接赋给目的操作数,例如: lea eax,[ebx+8] 就是将ebx+8这个值直接赋给eax mov eax,[ebx+8]则是把内存地址为ebx+8处的数据赋给eax。

  • 通用寄存器
32 位 16 位 8 位(高) 8 位(低)
EAX AX AH AL
EBX BX BH BL
ECX CX CH CL
EDX DX DH DL
32 位 16 位 32 位 16 位
ESI SI EBP BP
EDI DI ESP SP
  • 特殊用法
  1. 乘除指令默认使用EAX。它常常被称为扩展累加器(extended accumulator)寄存器。
  2. CPU 默认使用 ECX 为循环计数器。
  3. ESP 用于寻址堆栈(一种系统内存结构)数据。它极少用于一般算术运算和数据传输,通常被称为扩展堆栈指针(extended stack pointer)寄存器。
  4. ESI 和 EDI 用于高速存储器传输指令,有时也被称为扩展源变址(extended source index)寄存器和扩展目的变址(extended destination index)寄存器。
  5. 高级语言通过 EBP 来引用堆栈中的函数参数和局部变量。除了高级编程,它不用于一般算术运算和数据传输。它常常被称为扩展帧指针(extended frame pointer)寄存器。
  • 状态标志位
  1. 进位标志位(CF),与目标位置相比,无符号算术运算结果太大时,设置该标志位。
  2. 溢出标志位(OF),与目标位置相比,有符号算术运算结果太大或太小时,设置该标志位。
  3. 符号标志位(SF),算术或逻辑操作产生负结果时,设置该标志位。
  4. 零标志位(ZF),算术或逻辑操作产生的结果为零时,设置该标志位。
  5. 辅助进位标志位(AC),算术操作在 8 位操作数中产生了位 3 向位 4 的进位时,设置该标志位。
  6. 奇偶校验标志位(PF),结果的最低有效字节包含偶数个 1 时,设置该标志位,否则,清除该标志位。一般情况下,如果数据有可能被修改或损坏时,该标志位用于进行 错误检测。
  • 64位通用寄存器
操作数大小 可用寄存器
8 位 AL、BL、CL、DL、DIL、SIL、BPL、SPL、R8L、R9L、R10L、R11L、R12L、R13L、R14L、R15L
16 位 AX、BX、CX、DX、DI、SI、BP、SP、R8W、R9W、R10W、R11W、R12W、R13W、R14W、R15W
32 位 EAX、EBX、ECX、EDX、EDI、ESI、EBP、ESP、R8D、R9D、R10D、R11D、R12D、R13D、R14D、R15D
64 位 RAX、RBX、RCX、RDX、RDI、RSI、RBP、RSP、R8、R9、R10、R11、R12、R13、R14、R15
  • 整数常量
h 十六进制 r 编码实数
q/o 八进制 t 十进制(备用)
d 十进制 y 二进制(备用)
b 二进制
1
2
3
4
5
6
7
26         ;十进制
26d        ;十进制
11010011b  ;二进制
42q        ;八进制
42o        ;八进制
1Ah        ;十六进制
0A3h       ;十六进制
  • 整型常量表达式
运算符 名称 优先级
() 圆括号 1
+,- 一元加、减 2
*, / 乘、除 3
MOD 取模 3
+, - 加、减 4
  • 保留字列表。
$ PARITY? DWORD STDCALL
? PASCAL FAR SWORD
@B QWORD FAR16 SYSCALL
@F REAL4 FORTRAN TBYTE
ADDR REAL8 FWORD VARARG
BASIC REAL10 NEAR WORD
BYTE SBYTE NEAR16 ZERO?
C SDORD OVERFLOW?
CARRY? SIGN?
  • 定义段

.DATA 伪指令进行标识:
.data

.CODE 伪指令标识的程序区段包含了可执行的指令:
.code

.STACK 伪指令标识的程序区段定义了运行时堆栈,并设置了其大小:
.stack 100h

指令

一条指令有四个组成部分:

  1. 标号(可选)
  2. 指令助记符(必需)
  3. 操作数(通常是必需的)
  4. 注释(可选)

不同部分的位置安排如下所示:
[label: ] mnemonic [operands] [;comment]

标号

数据标号

1
count DWORD 100

代码标号

1
2
3
4
target:
        mov ax,bx
        ...
        jmp target

指令助记符

助记符 说明 助记符 说明
MOV 传送(分配)数值 MUL 两个数值相乘
ADD 两个数值相加 JMP 跳转到一个新位置
SUB 从一个数值中减去另一个数值 CALL 调用一个子程序

操作数

示例 操作数类型 示例 操作数类型
96 整数常量 eax 寄存器
2+4 整数表达式 count 内存

STC 指令没有操作数:
stc ;进位标志位置 1

INC 指令有一个操作数:
inc eax ;EAX 加 1

MOV 指令有两个操作数:
mov count, ebx ;将 EBX 传送给变量 count

IMUL 指令有三个操作数,第一个是目的操作数,第二个和第三个是进行乘法的源操作数:
imul eax,ebx,5

注释

  1. 单行注释,用分号(;)开始。汇编器将忽略在同一行上分号之后的所有字符。
  2. 块注释,用 COMMENT 伪指令和一个用户定义的符号开始。汇编器将忽略其后所有的文本行,直到相同的用户定义符号出现为止。
1
2
3
4
COMMENT !
        This line is a comment.
        This line is also a comment.
!

NOP(空操作)指令

1
2
3
4
5
6
7
8
9
.data                          ;此为数据区
sum DWORD 0                    ;定义名为sum的变量
.code                          ;此为代码区
main PROC
    mov eax,5                  ;将数字5送入而eax寄存器
    add eax,6                  ;eax寄存器加6
    mox sum,eax
    INVOKE ExitProcess,0       ;结束程序
main ENDP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
; AddTwo.asm -两个 32 位整数相加

.386
.model flat,stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD

.code
main PROC
mov  eax,5  ;将数字5送入eax寄存器
add      eax,6  ;eax寄存器加6

INVOKE ExitProcess,0
main ENDP
END main
  1. 第 3 行是 .386 伪指令,它表示这是一个 32 位程序,能访问 32 位寄存器和地址。
  2. 第 4 行选择了程序的内存模式(flat),并确定了子程序的调用规范(称为 stdcall)。其原因是 32 位 Windows 服务要求使用 stdcall 规范。
  3. 第 5 行为运行时堆栈保留了 4096 字节的存储空间,每个程序都必须有。
  4. 第 6 行声明了 ExitProcess 函数的原型,它是一个标准的 Windows 服务。原型包含了函数名、PROTO 关键字、一个逗号,以及一个输入参数列表。ExitProcess 的输入参数名称为 dwExitCode。

汇编伪指令回顾

CODE 的下一行声明程序的入口

1
2
.code
main PROC

ENDP 伪指令标记一个过程的结束。
main ENDP
END 伪指令标记一个程序的结束,并要引用程序入口:
END main

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
; AddTwo.asm - adds two 32-bit integers.
; Chapter 3 example

.386
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD

    00000000                            .code
    00000000                            main PROC
    00000000 B8 00000005                    mov eax, 5
    00000005 83 C0 06                       add eax,6

                                            invoke ExitProcess,0
    00000008 6A 00                          push        +000000000h
    0000000A E8 00000000 E                  call        ExitProcess
    0000000F                            main ENDP
                                        END main

数据类型以及数据定义详解

内部数据类型

类型 用法
BYTE 8 位无符号整数,B 代表字节
SBYTE 8 位有符号整数,S 代表有符号
WORD 16 位无符号整数
SWORD 16 位有符号整数
DWORD 32 位无符号整数,D 代表双(字)
SDWORD 32 位有符号整数,SD 代表有符号双(字)
FWORD 48 位整数(保护模式中的远指针)
QWORD 64 位整数,Q 代表四(字)
TBYTE 80 位(10 字节)整数,T 代表 10 字节
REAL4 32 位(4 字节)IEEE 短实数
REAL8 64 位(8 字节)IEEE 长实数
REAL10 80 位(10 字节)IEEE 扩展实数

数据定义语句

数据定义语法如下所示: [name] directive initializer [,initializer]… 下面是数据定义语句的一个例子:

1
count DWORD 12345
伪指令 用法 伪指令 用法
DB 8位整数 DQ 64 位整数或实数
DW 16 位整数 DT 定义 80 位(10 字节)整数
DD 32 位整数或实数
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
;AddTowSum.asm
.386
.model flat,stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD
.data
sum DWORD 0
.code
main PROC
    mov eax,5
    add eax,6
    mov sum,eax
    INVOKE ExitProcess,0
main ENDP
END main

定义 BYTE 和 SBYTE 数据

1
2
3
4
5
6
7
8
9
value1 BYTE  'A'    ;字符常量
value2 BYTE  0      ;最小无符号字节
value3 BYTE  255    ;最大无符号字节
value4 SBYTE -128   ;最小有符号字节
value5 SBYTE +127   ;最大有符号字节
value6 BYTE ?       ;变量

val1 DB 255    ;无符号字节
val2 DB -128  ;有符号字节

多初始值

1
list BYTE 10,20,30,40
偏移量 数值
0000 10
0001 20
0002 30
0003 40
1
2
3
list BYTE 10,20,30,40
     BYTE 50,60,70,80
     BYTE 81,82,83,84
1
2
list1 BYTE 10, 32, 41h, 00100010b
list2 BYTE 0Ah, 20h, 'A', 22h

list1与list2不同进制,但值相同

定义字符串

1
2
greeting1 BYTE "Good afternoon",0
greeting2 BYTE 'Good night',0

0作为结束标记

1
2
3
4
greeting1 BYTE "Welcome to the Encryption Demo program "
          BYTE "created by Kip Irvine.",0dh, 0ah
          BYTE "If you wish to modify this program, please "
          BYTE "send me a copy.",0dh,0ah,0

十六进制代码 0Dh 和 0Ah 也被称为 CR/LF (回车换行符)或行结束字符。

1
2
3
4
greeting1 BYTE "Welcome to the Encryption Demo program "

greeting1 \
BYTE "Welcome to the Encryption Demo program "

行连续字符(\)把两个源代码行连接成一条语句,它必须是一行的最后一个字符。上面的语句是等价的。

DUP 操作符

1
2
3
BYTE 20 DUP ( 0 )      ;20 个字节,值都为 0
BYTE 20 DUP ( ? )      ;20 个字节,非初始化
BYTE 4 DUP ( "STACK" ) ; 20 个字节:

定义 WORD 和 SWORD 数据

1
2
3
word1 WORD 65535    ;最大无符号数
word2 SWORD -32768  ;最小有符号数
word3 WORD ?        ;未初始化,无符号
1
2
val1 DW 65535   ;无符号
val2 DW -32768  ;有符号

也可以使用传统的 DW 伪指令


1
myList WORD 1,2,3,4,5
偏移量 数值
0000 1
0002 2
0004 3
0006 4
0008 5
1
array WORD 5 DUP (?) ; 5 个数值,未初始化

定义 DWORD 和 SDWORD 数据

1
2
3
val1 DWORD 12345678h    ;无符号
val2 SDWORD -2147483648 ;有符号
val3 DWORD 20 DUP (?)   ;无符号数组
1
2
val1 DD 12345678h ;无符号
val2 DD -2147483648 ;有符号
1
pVal DWORD val3
1
myList DWORD 1,2,3,4,5
偏移量 数值
0000 1
0004 2
0008 3
000C 4
0010 5

定义 QWORD 数据

1
2
quad1 QWORD 1234567812345678h
quad1 DQ 1234567812345678h