Bootstrap

X86汇编简介

第一天学逆向,从x86汇编开始QAQ(第一次写博客,也没有什么特殊内容)

X86汇编简介

什么是x86

x86泛指一系列基于Intel 8086且向后兼容的中央处理器指令集架构。最早的8086处理器于1978年由intel推出,为16位微处理器,x86架构是重要的可变指令长度的CISC。

什么是汇编?

汇编语言区别于高级语言和机器语言,简单来说就是把机器语言的指令用一些易于理解和记忆的单词、字母代替。

寄存器

寄存器是CPU内部的组成部分,是具有存储容量的高速存储部件,可以暂存指令,数据和地址

可以分为通用寄存器指令指针寄存器段寄存器标志寄存器、控制寄存器、浮点寄存器

通用寄存器

r开头的是8-byte,e开头/d结尾的是4-byte,ax、cx、dx、bx/r开头w结尾的是2-byte,l/b结尾的是1-byte

rax、rcx、rdx、rbx还有_h部分,代表低字节的高字节

指令指针寄存器

程序运行时,CPU会读取该寄存器中一条指令的地址,将指令传送到指令缓冲区后,改寄存器的值自动增加,CPU每次执行完一条指令,就会通过该寄存器读取并执行下一条指令。

不能直接修改指令指针寄存器的值,只能通过其他指令间接修改。

eg:jmp、retn、call

标志寄存器

*常用的状态标志

OF(Overflow Flag溢出标志位

如果指令运算结果发生溢出则OF=1,反之OF=0

SF(Sign Flag)符号标志位

如果指令运算结果是负数,SF=1,反之SF=0

ZF(Zero Flag)标志位

如果指令运算结果是则ZF=1,反之=0

CF(Carry Flag)进位标志位

如果指令运算发生进位或者借位则CF=1,反之CF=0

常见指令

数据传送指令可以将数据、地址立即数传送到寄存器或存储单元中

mov:把源操作数传送到目的操作数

格式:MOV dest, src

变化:

MOVSX:符号扩展的move指令

MOVZX:零扩展的move指令

数据传送指令-栈操作

栈是向低地址增长的

PUSH:把操作数进栈

同类指令:

PUSHA[D]:仅32位,64位不支持,将所有通用寄存器压栈

PUSHA[D|Q]:将寄存器的低16bits压栈,32位后可加d表示32bits,64位后可加q表示64bits,注意x86_64不支持PUSHFD

POP:将栈顶数据出栈到操作数

格式:POP dest

同类指令:

POPA[D]:仅32位,64位不支持,将所有通用寄存器出栈到各自寄存器

POPA[D|Q]:将标志寄存器的低16bits出栈,32位后可加d表示32bits,64位后可加q表示64bits,注意x86_不支持POPFD

LEA:将源操作数的有效地址传送到通用寄存器

格式:LEA reg, men

CMOV 系列指令,在一定条件下执行MOV

格式:CMOVXX dest, src

其中XX为不同的条件

XCHG:交换两操作数

格式:XCHG op1,op2

算数运算指令-加法指令

ADD:将源操作数和目的操作数相加,结果送到目的操作数。

ADC:将源操作数与目的操作数以及CF值相加,结果传送到目的操作数,即带进位的加法。

eg:Dest = dest + src

指令格式:ADD/ADC dest, src

INC(increase):目的操作数加一,结果送入目的操作数。

指令格式:INC dest

dest ++

算数运算指令-减法指令

SUB:将目的操作数减去源操作数,结果送入目的操作数。

CMP:将目的操作数减去源操作数,只修改状态标志位,不回送结果。

eg:CMP rax, 1,rax-1操作,但不会把rax-1的值赋给rax

SBB:将目的操作数减去源操作数,再减去CF值,结果送入目的操作数,即带错位的减法

指令格式:SUB/CMP/SBB dest, src

eg:sub rax, 1

rax -= 1

DEC:目的操作数减一,结果送入目的操作数

指令格式:DEC dest

dest - -

算数运算指令-乘法指令

MUL:无符号数乘法指令

指令格式:MUL src

解释:RDX:RAX = src * RAX

eg:mull rbx

rdx:rax = rbx * rax

IMUL:有符号数乘法指令

指令格式:IMUL [dest,] src

解释:dest = src *dest, dest 可以省略,省略时与MUL指令格式一致。

或者,IMUL dest, src1, src2

算数运算指令-除法指令

DIV:无符号除法指令

指令格式:DIV src

解释:RDX:RAX / src把商保存到RAX,余数保存到RDX

IDIV:有符号除法指令

指令格式:IDIV src

解释:RDX:RAX / src把商保存到RAX,余数保存到RDX

位运算指令

AND:与运算

TEST:与运算(只影响状态标志位,不回送结果)

OR:或运算

XOR:异或运算

指令格式

AND/TEST/OR/XOR dest, src

NOT:非运算

对目标操作数按位取反

**指令格式 **:NOT dest

逻辑移位

移位后最高位补0

SHL 逻辑左移

每移一位,最低位补0,最高位移入标志位CF中

SHR

每移一位,最低位移入标志位CF,最高位补0

算数移位

移位后最高位补符号位

SAL

与SHL完全一致

SAR

每移一位,最低位移入标志位CF,最高位补符号位

位运算指令

循环移位

ROL 循环左移

ROR 循环右移

流程控制指令

无条件转移指令

JMP 无条件转移

指令格式:JMP dest

解释:RIP = “dest”

CALL 过程调用

指令格式:CALL dest

解释:PUSH(RIP)、RIP = “dest”

CALL 0x1111

RET

指令格式:RET

解释:RIP = Pop()

指令指针寄存器

程序运行时,CPU会读取该寄存器中一条指令的地址,将指令传送到指令缓冲区后,该寄存器的值自动增加,CPU每次执行完一条指令,就会通过该寄存器读取并执行下一条指令。
不能直接修改指令指针寄存器的值,只能通过其他指令间接修改。
比如:jmp、retn、call
在这里插入图片描述

其他指令

NOP:空指令

指令格式:NOP

什么都不做,除了让RIP++外,不做任何操作

INT:中断指令

指令格式:INT n

其中n为中断类型号,比如INT3断点中断

寻址方式

处理器中寻找指令和操作数的方式

在x86_64架构中,有效地址(Effective Address)的计算公式如下:

Base + (Index * Scale) + Displacement

​ 其中:

​ Base:任何一个通用寄存器

​ Index:任何一个通用寄存器

​ Scale:一个参数因子,可以为1、2、4、8

​ Displacement:偏移量,一般来说可以是 8bits、16bits 或者 32bits 的一个有符号整数

![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=C%3A%5CUsers%5CADMIN%20YuHang在这里插入图片描述
%5CPictures%5CScreenshots%5C%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE(1&pos_id=img-phv1UIAx-1742128642729).png)

函数调用约定-x86 – 32位

stdcall调用(标准调用)

stdcall约定通常用于Windows API

参数从右向左入栈(即最后一个参数首先入栈)

调用者不需要清理堆栈,被调用函数负责清理堆栈

cdecl(C声明)

cdecl约定通常用于c语言标准库函数

参数从右向左入栈

调用者负责清理堆栈

fastcall(快速调用)

通过使用寄存器传递部分参数来优化函数调用优化性能

前两个整数参数通过寄存器(在x86架构下,通常是 ‘ecx’ 和 ‘edx’)传递,剩余参数从右向左入栈

被调用函数负责清理堆栈

![外链图片转存失败,源站可能有防盗链机制,建议在这里插入图片描述

汇编代码 - if 语句/switch语句/while语句/for语句(没学太明白QAQ)

;