逆向基础 || x86汇编

x86汇编

1.寄存器

  • 本环境寄存器大小为2字节 = 1 字型 = 16 bit

  • 早期的 x86 CPU 只有8个寄存器,而且每个都有不同的用途,通过DOS环境下我们可以看到有各种寄存器,接下来就一步步的认识它们!

AX      --> ah al
BX      --> bh bl
CX      --> ch cl
DX      --> dh dl
  • 上面4种通用寄存器,由于兼容早期数据大小,将一个16位大小的寄存器分为俩个8位的 xh属于高地址 xl属于低地址

SP      栈顶指针
BP      基址指针
SI      用于指向源数据的起始地址
DI      用于指向源数据的目标地址
DS      数据段的段地址默认寄存器
ES      附加段地址
SS      栈段的默认段地址存放处
CS      代码段的默认段地址存放处
IP      下一条指令的偏移地址

  • 标志寄存器

有的指令会影响标志寄存器 比如: add, sub, mul, div, inc, or, and 大多数为算数和逻辑指令

有的指令没有影响 比如:mov, push, pop 大多数为传送指令

ZF-零标准(Zero Flag)
    ZF = 1 表示 "结果为0" 1表示"逻辑为真"  ----->  ZR
    ZF = 0 表示 "结果为1" 0表示"逻辑为假"  ----->  NZ
​
PF-奇偶标志(Parity Flag)
    当执行的结果的二进制1的个数为偶数 PF的值为1 ---> PE
    ......                  奇数 PF的值为0 ---> PO
​
SF-符号标志(Sign Flag)
    当执行的结果为负 SF=1 ---> NG
    当执行的结果为正 SF=0 ---> PL
​
CF-进位标志(Carry Flag)
    当计算时对于有效位向更高位借位or进位 CF=1 ---> CY
    无                              CF=0 ---> NC
​
OF-溢出标志(Overflow Flag)
    当进行有符号计算数 有溢出 OF=1 ---> OV
                    无溢出 OF=0 ---> NV
​
DF-方向标志(Direction Flag)
​
​
CF与OF的区别:
    CF对于无符号运算有意义的 进|借位标志
    OF对于有符号运算有意义的 溢出标志

2.指令

伪指令

1) .modle
.model flat,stdcall
​
model伪指令告诉汇编程序使用哪一种存储模式:
    32位程序总是使用平面(flat)存储模式,它与处理器的保护模式相关联。关键字stdcall在调用程序时告诉汇编器,怎样管理运行时堆栈
    .STACK 伪指令,它告诉汇编器应该为程序运行时堆栈保留多少内存字节

2) .STACK

定义一个栈段后面跟数值大小

.stack 1024

3) . ENDS

用于结束块

codesg segment
......
codesg ends

4) . END

用于结束程序

start : 
........
end start

5) ALIGN

汇编指令

ALIGN 伪指令将一个变量对齐到字节边界、字边界、双字边界或段落边界

ALIGN 4     ;偏移量按4对齐

1) MOV
将bx寄存器里面的值移到ax寄存器里
mov ax,bx

2) MOVZX 和 MOVSX

MOVZX 指令(进行全零扩展并传送)将源操作数复制到目的操作数,并把目的操作数 0 扩展到 16 位或 32 位。这条指令只用于无符号整数,有三种不同的形式:

movzx 32位通用寄存器, 8位通用寄存器/内存单元
movzx 32位通用寄存器, 16位通用寄存器/内存单元
movzx 16位通用寄存器, 8位通用寄存器/内存单元

MOVSX将用操作数B的符号位扩展填充操作数A的余下空间,如果是负数则符号位为1,如果是正数则和MOVZX功能相同:

MOVSX A,B

3) XCHG

交换两个操作数内容,不能直接交换两个内存操作数

XCHG ax,ax
XCHG ax,bx
XCHG bx, ax

4) INC 和 DEC

INC(增加)和DEC(减少)指令分别表示寄存器加 1 和减 1:

inc ax
dec ax

不支持直接对内存进行操作

5) ADD 和 SUB

操作数相加减

add ax,bx   将ax,bx的寄存器值相加并放入ax寄存器中
sub ax,bx   将ax,bx的寄存器值相减并放入ax寄存器中

6) NEG

计算一个数的二进制数补码

01100100  0x64   按位取反加1 --->
10011100  9Ch

7) JMP

JMP 指令无条件跳转到目标地址, 并被汇编器转换为偏移量。

JMP 标志符
​
gool:
    ...
    ...
    jmp gool
​

8) LOOP

loop指令与cx寄存器绑定,执行多少次由cx值决定

mov cx,10
s:
    ...
    ...
    loop s

首先将cx=cx-1,然后判断是否为0,不为0继续执行

9) PUSH,POP

push时首先减少sp的值,在将值复制到栈中

push ax

pop时首先增加sp的值,指向高地址,在取出值赋值给寄存器中

pop ax

10) PUSHFD,POPFD

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

PUSHFD          ;保持标志寄存器
POPFD           ;恢复标志寄存器

11) PUSHAD, PUSHA, POPAD, POPA

这里的D可以想成是double,对32位寄存器操作

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

  • PUSHA 指令按序(AX、CX、DX、BX、SP、BP、SI 和 DI)将 16 位通用寄存器压入堆栈;POPA 指令按照相反顺序将同样的寄存器弹出堆栈

12) CALL和RET

CALL 指令调用一个过程,会将当前call指令的下一条指令的地址放到堆栈中

ret返回时就是取堆栈中的地址然后改sp的值,指向call的下一条指令

call chunk
chunk:
    ...
    ...
    ret

13) AND,OR, XOR, NOT
and ax,bx   ; ax和bx的二进制数进行逻辑与运算
or ax,bx    ; ax和bx的二进制数进行逻辑或运算
xor ax,bx   : 按位异或
not ax      ; 按位取反

14) TEST

TEST与AND 指令唯一不同的地方是,TEST 指令不修改目标操作数。TEST 指令允许的操作数组合与 AND 指令相同。在发现操作数中单个位是否置位时,TEST 指令非常有用

;       测试AL寄存器的位0和位3是否为1
TEST al, 00001001b

当所以测试位都为0时,零标志位ZF才为1

15) CMP指令

比较整数: 功能相当于减法指令,只是不保存结果但是会对标志寄存器产生影响

cmp ax,bx
标志位

如果比较的是两个无符号数,则零标志位和进位标志位表示的两个操作数之间的关系如表所示:

CMP结果ZF(零标志)CF(进位标志)
ax > bx00
ax < bx01
ax = bx10

如果比较的是两个有符号数,则符号标志位(SF)、零标志位(ZF)和溢出标志位(OF)表示的两个操作数之间的关系如表所示:

CMP结果符号标志位(SF)零标志位(ZF)溢出标志位(OF)
ax > bx000
ax < bx101
ax = bx010

一般而言,CMP指令与跳转指令相结合

CMP指令的作用在于比较之后设置标志位,而跳转指令通过判断标志位来进行跳转,达到if语句的效果

16) 条件跳转指令
指令含义测试条件
je/jz相等/结果不为0ZF = 1
jne/jnz不等/结果不为0ZF = 0
js结果为负SF = 1
jns结果非负SF = 0
jo结果溢出OF = 1
jno结果未溢出OF = 0
jp奇偶位为1PF = 1
jnp奇偶位为0PF = 0
jb/jnae/jc低于/不高于等于/有借位CF = 1
jnb/jae/jnc不低于/高于等于/无借位CF = 0

根据无符号数的结果进行转移指令

jb/jnae/jc低于则转移CF = 1
jnb/jae/jnc高于则转移CF = 0
jna/jbe不高于则转移CF = 1 or ZF = 1
ja/jnbe高于则转移CF = 0 and ZF = 0
j-Jump  e-Equal n-Not   b-Below a-Above L-less  g-Greater   
s-Sign  C-Carry p-Parity    o-Overflow  z-Zero

17) 移位和循环移位指令
SHR右移RCR带进位的循环右移
SHL左移RCL带进位的循环左移
SAR算数右移SHRD双精度右移
SAL算数左移SHLD双精度左移
ROR循环右移ROL循环左移

移位

  • 逻辑移位:空出来的位用 0 填充;

  • 算数移位:空出来的位用原数据的符号位填充;

循环移位

  • 以循环方式来移位即为位元循环

  • 当多字节整数以四位为单位进行循环移位时,其效果相当于一次向右或向左移动一个十六进制位。例如,将 6A4Bh 反复循环左移四位,最后就会回到初始值

mov ax, 6A4Bh
rol ax, 4              ; AX = A4B6h
rol ax, 4              ; AX = 4B6Ah
rol ax, 4              ; AX = B6A4h
rol ax, 4              ; AX = 6A4Bh

18) MUL指令: 无符号乘法

被乘数放在AX里,如果是使用8位,放在al里

mov al,10h
mov bl,10h
mul bl          ; al = al * bl
​
mov ax,10h
mov bx,10h
mul bx          ; ax = ax * bx
  • 当 AX 乘以一个 16 位操作数时,乘积存放在 DX 和 AX 寄存器对中。其中,乘积的高 16 位存放在 DX,低 16 位存放在 AX。如果 DX 不等于零,则进位标志位置 1,这就意味着隐含的目的操作数的低半部分容纳不了整个乘积

  • 64 位模式下,MUL 指令可以使用 64 位操作数。一个 64 位寄存器或内存操作数与 RAX 相乘,产生的 128 位乘积存放到 RDX:RAX 寄存器中

19) IMUL指令: 有符号乘法
  • 与 MUL 指令不同,IMUL 会保留乘 积的符号,实现的方法是,将乘积低半部分的最高位符号扩展到高半部分

20) DIV指令: 无符号除法

被除数、除数、商和余数之间的关系:

被除数除数余数
AL8位寄存器ALAH
AX16位寄存器AXDX
EAX32位寄存器EAXEDX
  • 64 位模式下,DIV 指令用 RDX:RAX 作被除数,用 64 位寄存器和内存操作数作除数, 商存放到 RAX,余数存放在 RDX 中

AL中放商                   AH中放余数 
mov al, 0083h              ; 被除数
mov bl, 2                  ; 除数
div bl                     ; AL = 41h, AH = Olh

21) IDICV: 有符号除法

有符号除法几乎与无符号除法相同,只有一个重要的区别:在执行除法之前,必须对被除数进行符号扩展

符号扩展是指将一个数的最高位复制到包含该数的变量或寄存器的所有高位中

符号拓展指令有:CBW,CWD,CDQ,分别对应:字节转字,字转双字,双字转四字

其他

1.跳转距离

1) 俩个段内转移
  • jmp shor 标号

IP = IP + 8位位移
​
8位位移 = "标号"处的地址 - jmp指令后的第一个字节的地址
​
8位位移的范围为-128~127 用补码表示;

  • jmp near ptr 标号

IP = IP + 16位位移
​
16位位移 = "标号"处的地址 - jmp指令后的第一个字节的地址
​
16位位移的范围为-32769~32767 用补码表示;

2) 远转移: jmp far ptr 标号
远转移jmp far ptr 标号近转移jmp near ptr 标号
段间转移段内转移
far ptr 指明了跳转的目标地址,包含cs:ipnear ptr 指明了相对于当前ip的偏移地址

2.转移地址在内存中的jmp指令

jmp word ptr 内存单元地址jmp dword ptr 内存单元地址
段内转移段间转移
从内存单元地址处开始存放着一个字,是转移的目的偏移地址从内存单元地址处开始存放着俩个字,高地址处目的段地址,低地址处是转移的目的偏移地址

3. jmp bx ;16位寄存器

4. jmp总结

5. offset 操作符

offset 用于取标号的偏移地址

​
start:
    mov ax, bx ;    “mov ax, bx”的机器码占两个字节
    mov si, offset start    start是标号
    mov di, offset s0
​
    mov ax, cs:[si]
    mov cs:[di], ax
​
s0: nop ; nop的机器码占一个字节
    nop
​

6.块级转移数据

movsb movsw 的使用与DF标志密切相关

movsb 默认将 ds:si 的一个字节数据移到 es:di中

1) movsb
  • movsb 当DF中值为0 移动后偏移地址加一

  • 当DF中值为1 移动后偏移地址减一

2) movsw
  • movsw 当DF中值为0 移动后偏移地址加二

  • 当DF中值为1 移动后偏移地址减二

start: 
    mov ax,0f000h
    mov ds,ax
    mov si,0ffffh
    mov ax,data
    mov es,ax
    mov di,15
    mov cx,16
​
    std        ; std  将 DF标志的值改为1(DF标志是位移标志通常于movsb.movsw连用) 
    rep movsb  ; rep 和loop一样循环次数跟 cx相关 
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值