汇编指令细节篇

前言

本篇基于X86架构,Intel格式。
AT&T格式语义上差不多,语法上特征%。

汇编注意

  • 伪指令
  • 保留字
  • 标识符

  • 模块:OEJ文件。
  • 条件转移范围-128—127。
  • BCD码的本质是十进制数 //二进制编码的十进制数。
  • 被显示的字符串必须以‘$’结束。
  • 以字母开头的十六进制数必须加个前置 0,以防汇编器将其解释为标识符。
  • 掩码是一串二进制代码对目标字段进行位与运算,屏蔽当前的输入位。

  • 列表文件(信息很多)
    汇编器读取源文件,并生成目标文件,即对程序的机器语言翻译。或者,它也会生成列表文件。
    列表文件 (listing file) 包括了程序源文件的副本,再加上行号、每条指令的数字地址、每条指令的机器代码字节(十六进制)以及符号表。

变量概念

内存单元的符号地址。

  • 变量最重要的三个属性
    段属性
    偏移属性
    类型属性

保留字

$
?
@B(预定义符号)
@F
等等查表说明书

预定义说明内容

.386 //使用386指令集
.model flat //使用flat平坦内存模式
option casemap:none //大小写敏感

寄存器

  • 特别eflags(非所有)

PF 低8位有效 //奇偶标志位PF检测最低有效字节(低8位)中 1 的个数。

AF Bit3向Bit4有进位(借位)

  • 间址寄存器
    BX,BP,SI,DI

  • 控制标志位3个

TF(Trap Flag)

IF(Intcrrupt Flag)

DF(Direction Flag)

assume

assume 将段名和对应的段寄存器关联起来

$当前地址计数器(有点指针的味道)

最重要的符号之一被称为当前地址计数器(current location counter),表示为 $。
例如,下面的语句声明了一个变量 selfPtr,并将其初始化为该变量的偏移量:
selfPtr DWORD $

EQU(类似define)

INC | DEC

INC 和 DEC 指令不会影响进位标志位CF。

MOV 操作字符串

Di必须属于ES段

64位MOV指令

  • 类一,MOV RAX 常量
    操作常数时,多出来的高位清零。

  • 类二,MOV RAX 内存操作数
    8位或16位内存操作数送入 RAX 的低位,但目标寄存器的高位不受影响。

4种基本I/O控制方式

无条件传送
查询工作方式
中断方式
DMA方式

MOVZX | MOVSX

MOVZX无符号扩展传送
MOVSX有符号扩展传送

LAHF | SAHF 保存eflags寄存器

LAHF加载EFLAGS寄存器内容到AH
SAHF保存AH内容到EFLAGS寄存器

XCHG

XCHG交换数据(不能内存和内存交换)

NEG

NEG(非)指令通过把操作数转换为其二进制补码,将操作数的符号取反。
在非零操作数上应用 NEG 指令总是会将进位标志CF位置 1。

ALIGN

ALIGN伪指令:对齐一个变量
注:靠填充CC对齐。

LENGTHOF运算符

如果数组定义占据了多行,那么 LENGTHOF 只针对第一行定义的数据。

硬件如何检测溢出?

计算结果的最高有效位产生的进位(C即F位)与结果的最高位进行 异或操作,异或的结果存入溢岀标志位。

LABEL伪指令(类似替代下方附近的别名)

插入一个标号,并定义它的大小属性,但是不为这个标号分配存储空间

LOOP

两步:

  • ECX 减 1。
  • 将 ECX 与 0 比较。

循环目标必须距离当前地址计数器 -128 到 +127 字节范围内。

PUSHFD | POPFD (操作eflags)

PUSHFD 指令把 32 位 EFLAGS 寄存器内容压入堆栈。
POPFD 指令则把栈顶单元内容弹出到 EFLAGS 寄存器。

PUSHAD | POPAD(操作通用寄存器)

PUSHAD 指令按照 EAX、ECX、EDX、EBX、ESP(执行 PUSHAD 之前的值)、EBP、ESI 和 EDI 的顺序,将所有 32 位通用寄存器压入堆栈。
POPAD 指令按照相反顺序将同样的寄存器弹出堆栈。

USES运算符

USES 运算符与 PROC 伪指令一起使用,让程序员列出在该过程中修改的所有寄存器名(即保护此寄存器原先的环境)。
USES 告诉汇编器做两件事情:

  • 第一,在过程开始时生成 PUSH 指令,将寄存器保存到堆栈;
  • 第二,在过程结束时生成 POP 指令,从堆栈恢复寄存器的值。

Microsoft x64 调用规范

Microsoft 在 64 位程序中使用统一模式来传递参数并调用过程,称为 Microsoft x64 调用规范。
程序员只有在调用 Windows API 的函数或用 C/C++ 编写的函数时,才会使用这个调用规范。该调用规范的一些基本特性如下所示:

  1. CALL 指令将 RSP(堆栈指针)寄存器减 8,因为地址是 64 位的。

  2. 前四个参数依序存入 RCX、RDX、R8 和 R9 寄存器,并传递给过程。如果只有一个参数,则将其放入 RCX。如果还有第二个参数,则将其放入 RDX,以此类推。其他参数,按照从左到右的顺序压入堆栈。

  3. 调用者的责任还包括在运行时堆栈分配至少 32 字节的影子空间(shadow space),这样,被调用的过程就可以选择将寄存器参数保存在这个区域中。

  4. 在调用子程序时,堆栈指针(RSP)必须进行 16 字节边界对齐(16 的倍数)。CALL 指令把 8 字节的返回值压入堆栈,因此,除了已经减去的影子空间的 32 之外,调用程序还必须从堆栈指针中减去 8。

TEST 指令

TEST 指令是一种非破坏性的 AND 操作,并适当地设置 CPU 标志位。

NOT

NOT 指令不影响标志位。

CMP

CMP(比较)指令执行从目的操作数中减去源操作数的隐含减法操作,并且不修改任何操作数。

STC | CLC (控制CF)

stc CF进位标志位置 1
clc CF进位标志位清零

STD | CLD(DF)

STD 将方向标志位DF置1
CLD 将方向标志位DF清零

STI | CLI(interrupt register)

STI 允许中断发生
CLI 禁止中断发生
这两个指令只能在内核模式下执行,不可以在用户模式下执行

条件跳转指令可以分为四个类型

基于特定标志位的值跳转
基于两数是否相等,或是否等于(E)CX 的值跳转
基于无符号操作数的比较跳转
基于有符号操作数的比较跳转

AND | OR 作用

AND 屏蔽作用
OR 保留作用

字节宽度转换指令

CBW 字节转字指令
CWD 字转双字指令
CDQ 双子转四字

位移动(bit shifting)

逻辑左移逻辑右移
SHL逻辑左移SHR逻辑右移

逻辑移位 (logic shift),空出来的位用 0 填充

算术左移算术右移
SAL算术左移SAR算术右移

算术移位 (arithmetic shift),空出来的位用原数据的符号位填充

循环左移循环右移
ROL循环左移ROR循环右移

最高(低)位复制到进位标志位和最低(高)位

左移右移
RCL带进位的循环左移RCR带进位的循环右移
SHLD双精度左移SHRD双精度右移

ADC | SBB

ADC指令:带进位加法
SBB指令:带借位减法

ENTER | LEAVE

  • ENTER 指令为被调用过程自动创建堆栈帧。

    把 EBP 入栈 (push ebp)
    把 EBP 设置为堆栈帧的基址 (mov ebp, esp)
    为局部变量保留空间 (sub esp, numbytes)
    用法:ENTER numbytes, nestinglevel
    这两个操作数都是立即数。Numbytes 总是向上舍入为 4 的倍数,以便 ESP 对齐双字边界。
    Nestinglevel 确定了从主调过程堆栈帧复制到当前帧的堆栈帧指针的个数。

  • LEAVE 指令反转了之前的 ENTER 指令操作:恢复了过程被调用时 ESP 和 EBP 的值。

ADDR (配合INVOKE)

ADDR 运算符只能与 INVOKE 一起使用,
在使用 INVOKE 调用过程时,它可以传递指针参数。

函数三部曲

PROC 定义
PROTO 声明
INVOKE 调用

操作字符串

注:[x]:B,W,D
movsx 传送字符串
cmpsx 比较字符串
scasx 扫描字符串
stosx 保存字符串
lodsx 从字符串加载到累加器


配合REP指令使用
REPNE SCASB 不相等则重复查找的字符串搜索指令,
在使用此指令之前bai要指du定:查找的基址DS,偏移指针DI,和查找长度CX以及目标字符AL(以ascii存放)

扫描DS:DI所指字符是否与AL中字符匹配,若不匹配,则零标志ZF=0,DI++,CX–直到找到匹配的字符或者找遍整个指定的区域(即CX为0为止)
若找到了与AL值相等的字符ascii码,改变ZF=1,退出查找


LODSB、LODSW 和 LODSD 指令分别从 ESI 指向的内存地址加载一个字节或一个字到 AL/AX/EAX。
ESI 按照方向标志位的状态递增或递减。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值