汇编语言与逆向技术基础 三、汇编语言基础
汇编语言与逆向技术基础 三、汇编语言基础
本章知识点
- 汇编语言的基本元素
- 定义数据
- 符号常量
- 汇编、链接和运行程序
汇编语言的基本元素
基本元素
- 整数常量、整数表达式
- 实数常量
- 字符常量、字符串常量
- 保留字、标识符
- 指令、伪指令、NOP 指令
整数常量
[{+/-}]数字[基数]
基数后缀 Radix
h 十六进制、 q/o 八进制、d 十进制、b 二进制
r 编码实数
如果整数常量后面没有基数后缀,默认十进制
10, 10d, 10o, 10h, 0A0h, 10b
以字母开头的十六进制常量前面必须加 0
整数表达式
- 包含整数值和算数运算符的数学表达式
- 表达式结果不能超过 32bits 的表示范围,超过了会溢出
- MOD: 取余运算
算数运算符的优先级
- () 优先级 1
- * / MOD 优先级2
- + - 的优先级3
实数常量
- 十进制实数
- 编码(十六进制)实数
十进制实数常量
- -1.11E-5,2.、+3.0、2.E5
- 十进制实数常量由符号、整数、小数点、小数和指数组成
- [sign]integer.[integer][exponent]
- 至少一个数字和一个小数点
字符常量
- 单引号或双引号括起来的单个字符
- 汇编器会将其转化为 ASCII 编码
- ‘A’ “B”
字符串常量
- 以单引号或者双引号括起来的一串字符
- ‘ABC’ “ABC”
- 嵌套引号
保留字
- 指令助记符:MOV ADD
- 伪指令:INCLUDE PROC
- 属性:BYTE WORD
- 预定义符号:$ ?
标识符
- 标识符是程序员选择用来表示变量、常量、过程、代码的标号
- 包含1~247个字符
- 大小写不敏感(MASM 默认)
- 第一个字符必须是字母、下划线、@、?、$
- 第一个字符不能是数字(对比十六进制整数)
指令
- 汇编语言中的指令是一条汇编语句
- 汇编器把汇编指令翻译成对应的机器指令
- 标号
- 指令助记符
- 操作数
- 注释
标号
- 标号是充当指令或数据位置标记的标识符
- 数据标号:标识变量的地址
- 代码标号:标识代码的地址
数据标号
标识变量的地址,方便变量的引用
count DWORD 100
array DWORD 100, 101, 102, 103
相对 .data 数据段在内存其实地址的偏移
OFFSET 偏移
获取数据标号的内存偏移地址
.data
str_hello BYTE “Hello World!”, 0
.code
mov eax, OFFSET str_hello
代码标号
- 表示代码的地址,必须以冒号(:)结尾
- 通常作为跳转、循环指令的目标地址
target:
mov eax, 100h
…
jmp target
指令助记符
指令助记符是一个简短的单词,用于表示一条指令,如 mov add sub mul jmp call
操作数
操作数是指令的操作对象,包含:寄存器、内存、常量、I/O端口
- inc eax %eax寄存器的值加1
- mov count, ebx
- mov 指令有两个操作数:count、ebx
- 第一个操作数是目的操作数
- 第二个操作数是源操作数
注释
单行注释
- mov count, ebx==; SAVE RESULT TO COUNT==
块注释:COMMENT伪指令和用户定义的符号
COMMENT !
This is a comment
!
NOP 指令
- 空操作,用于计时循环
- NOP 指令占用 1 个字节的内存
- 用于后继指令的对齐
- IA-32 处理器从额数双字地址处加载代码和数据时更加快速
伪指令
伪指令内嵌在汇编语言源代码中,由汇编器识别、执行相应动作的命令
用于定义变量、段、过程、汇编器选项等
定义变量
my_var DWORD 100h; DWORD 伪指令
mov eax, my_var; mov 指令
定义段 Segment 如 .data .code .stack
定义过程 Procedure 如 PROC ENDP
允许或禁止汇编器的某些特性 如 OPTION .386 .MODEL
定义数据
内部数据定义
- MASM 内部以数据位的个数定义了多种数据类型
- BYTE db 8bit
- WORD dw 16bit
- DWORD dd 32bit
- QWORD dq 64bit
- MASM 汇编器默认情况下大小写不敏感
- DWORD 可以写成 dWorD DwoRd
数据定义语句
- 为变量在内存中保留存储空间
- 为变量指定一个名字(数据标号)
- [变量名] 数据定义伪指令 初始值
初始值
- 数据定义语句中要指定初始值
- 多个初始值用逗号隔开
- 可以指定初始值为 0
- ? 表示在程序运行的时候初始化该变量
数据声明的位置
- .data 段声明初始化的变量
- .data? 段声明未初始化的变量
定义字符串
str_hello BYTE “Hello World!”, 0Dh, 0Ah ,
BYTE “I love assembly language”,
BYTE 0Dh, 0Ah, 0
- 0Dh 和 0Ah 是 CR/LF (回车、换行)的 ASCII 编码
- 字符串的结尾是 0
DUP 伪指令 (Duplicate)
- 为字符串或者数组分配内存空间
- BYTE 20 DUP (0); 20 个字节的内存空间
- BYTE 4 DUP (“Hello”); 20 个字节,连续的 4 个“Hello“, 每个 ”Hello“ 5字节
符号常量
- 符号常量(或符号定义),将标识符与整数表达式或文本联系起来
- 符号常量不占用存储空间
- 变量占用存储空间
等号伪指令
等号伪指令,将符号名和整数表达式联系起来
COUNT = 500
mov eax, COUNT
易于阅读与维护,减少程序修改时的查找与替换次数
计算数组和字符串的大小
MASM 用 $ 运算符存储当前语句的地址偏移值
$ 可以用来计算数组或字符串大小
str_size = ($ - str_hello)
array_size = ($ - dw_array)/4
EQU 伪指令
EQU 伪指令将符号名与整数表达式或任意文本联系起来
name EQU expression
name EQU symbol
name EQU <text>
汇编、链接和运行程序
- 源文件:用文本编辑器编写的 asm 文本文件
- 汇编:汇编器把汇编源文件翻译成机器语言,生成目标文件
- 链接:链接器从库中复制所需的过程,并将其同目标文件合并在一起生成可执行文件