汇编语言与逆向技术基础 三、汇编语言基础

本章知识点

  • 汇编语言的基本元素
  • 定义数据
  • 符号常量
  • 汇编、链接和运行程序

汇编语言的基本元素

基本元素

  • 整数常量、整数表达式
  • 实数常量
  • 字符常量、字符串常量
  • 保留字、标识符
  • 指令、伪指令、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 文本文件
  • 汇编:汇编器把汇编源文件翻译成机器语言,生成目标文件
  • 链接:链接器从库中复制所需的过程,并将其同目标文件合并在一起生成可执行文件