继续更新个人的学习条记,
其它条记传送门
逆向基础条记一 进制篇
逆向基础条记二 数据宽度和逻辑运算
逆向基础条记三 通用寄存器和内存读写
逆向基础条记四 堆栈篇
逆向基础条记六 汇编跳转和比较指令
逆向基础条记七 堆栈图(重点)
逆向基础条记八 反汇编分析C语言
逆向基础条记九 C语言内联汇编和调用协定
逆向基础条记十 汇编寻找C步伐入口
逆向基础条记十一 汇编C语言根本类型
逆向基础条记十二 汇编 全局和局部 变量
逆向基础条记十三 汇编C语言类型转换
逆向基础条记十四 汇编嵌套if else
逆向基础条记十五 汇编比较三种循环
逆向基础条记十六 汇编一维数组
逆向基础条记十七 汇编二维数组 位移 乘法
逆向基础条记十八 汇编 结构体和内存对齐
逆向基础条记十九 汇编switch比较if else
逆向基础条记二十 汇编 指针(一)
逆向基础条记二十一 汇编 指针(二)
逆向基础条记二十二 汇编 指针(三)
逆向基础条记二十三 汇编 指针(四)
逆向基础条记二十四 汇编 指针(五) 系列完结
EFLAGS寄存器
进位标记CF(Carry Flag)
假如运算结果的最高位产生了一个进位或借位,那么,其值为1,否则其值为0
例子:
MOV AL,0xFFADD AL,10x80+0x40
加黑的为最高位
0x80:0 1000 0000
0x40:0 0100 0000
结果为1100 0000 最高位并没有发生变化,于是CF位为0
0x80-0x40
注意这里借位的位是1000 0000中的加黑部分
而非0 1000 0000这里的最高位
结果为0100 0000 最高位并没有发生变化,于是CF位为0
0x80-0x81
0x80:1000 0000
0x81:1000 0001
结果为1111 1111= -1,最高位被借位,于是CF位为1
奇偶标记PF(Parity Flag)
奇偶标记PF用于反映运算结果中最低有用字节中“1”的个数的奇偶性
假如“1”的个数为偶数,则PF的值为1,否则其值为0。
指令指令执行后AL的结果PFMOV AL,300111ADD AL,301101ADD AL,210000例:
MOV AX,803ADD AX,10x803: 0000 1000 0000 0011
执行结果
0x804: 0000 1000 0000 0100 总共2个1 ,PF应为1,但实际运行结果PF为0
因为PF是根据最低有用字节来看,即804背面04的这部分
04: 0000 0100 总共1个1,所以PF为0
辅助进位标记AF(Auxiliary Carry Flag)
在发生下列环境时,辅助进位标记AF的值被置为1,否则其值为0:
- 在字利用时,发生低字节向高字节进位或借位时
- 在字节利用时,发生低4位向高4位进位或借位时
AF与数据宽度相关
32位时 FFFF F FFF
16位时 FF F F
8位时 F F
加黑的字体为AF标记位判断的位置,假如该位置要向前进位则AF为1,否则为0,和CF相似,不过判断的位置差别
32位例:
MOV EAX,55EEFFFFADD EAX,216位例:
MOV AX,5EFEADD AX,28位例:
MOV AL,4EADD AL,2零标记ZF(Zero Flag)
零标记ZF用来反映运算结果是否为0
假如运算结果为0,则其值为1,否则其值为0
作用:在判断运算结果是否为0时,可使用此标记位
例子:
XOR EAX,EAX通过xor将eax清零,会改变zf标记位为1
MOV EAX,0通过MOV将EAX赋值为0,非运算,不改变zf标记位
符号标记SF(Sign Flag)
符号标记SF用来反映运算结果的符号位,它与运算结果的最高位雷同
例子:
MOV AL,7FADD AL,2溢出标记OF(Overflow Flag)
溢出标记OF用于反映有符号数加减运算所得结果是否溢出
注意与CF区分!!!
最高位进位与溢出的区别:
进位标记表示无符号数运算结果是否超出范围.
溢出标记表示有符号数运算结果是否超出范围.
溢出主要是给有符号运算使用的,在有符号的运算中,有如下的规律:
- 正 + 正 = 正 假如结果是负数,则阐明有溢出
- 负 + 负 = 负 假如结果是正数,则阐明有溢出
- 正 + 负 永远都不会有溢出
无符号、有符号都不溢出例
MOV AL,8ADD AL,8AL的数据宽度为8,即
无符号数范围为0~FF即0~255
8+8=16在0~255内 不溢出
有符号数的范围为
正数:0~7F 即0~127
负数:80~FF 即 -128~0
8+8=16 在0~127内 两正数相加结果仍为正数,不溢出
无符号溢出、有符号不溢出例
MOV AL,0FFADD AL,2无符号数时
FF+2=255+2=257 在0~255外,溢出
有符号数时
FF+2=-1+2=1
正 + 负 永远都不会有溢出
无符号不溢出、有符号溢出例
MOV AL,7FADD AL,2无符号数时
7F+2=127+2=129 在0~255内 不溢出
有符号数时
7F+2=0x81在80~FF (负数范围)内,两正数相加结果为负数,溢出
无符号、有符号都溢出
MOV AL,0FEADD AL,80无符号数时
FE+2=254+2=256=0x100 在0~255外 溢出
有符号数时
FE+2=0x100在0~FF外,溢出
CPU如何计算OF位
起首引入两个概念:
对于一个有符号数:如0x80和0xC0
符号位有进位
0x80:1 000 0000
0xC0:1 100 0000
最高有用数值位向符号位产生的进位
0x80:1 0 00 0000
0xC0:1 1 00 0000
接下来看一组汇编指令
MOV AL,80ADD AL,0C0就是运算0x80+0xc0
0x80:1 0 00 0000
0xC0:1 1 00 0000
符号位1+1有产生进位,于是符号位有进位为1
最高有用数值位向符号位产生的进位0+1没有产生进位,于是最高有用数值位向符号位产生的进位为0
OF = 符号位有进位 xor 最高有用数值位向符号位产生的进位
OF = 1 xor 0 = 1 所以此时OF=1
方向标记DF(Direction Flag)
DF:方向标记位
DF=1时串利用为减地址方式 DF=0为增地址方式
下面的MOVS指令有阐明DF的详细应用
相关汇编指令
符号含义r寄存器m内存imm立刻数r88位通用寄存器m88位内存imm88位立刻数ADC指令:带进位加法
格式:ADC R/M,R/M/IMM 两边不能同时为内存 数据宽度要一样
例:
MOV AL,1MOV CL,2手动修改CF为1ADC AL,CL计算结果为4,原本1+2=3,但是现在变成了4,注意与ADD的区别就在于进位
SBB指令:带借位减法
格式:SBB R/M,R/M/IMM 两边不能同时为内存 数据宽度要一样
MOV AL,4MOV CL,2手动修改CF为1SBB AL,CL计算结果为1,原本4-2=2,但是现在变成了1,注意与SUB的区别就在于进位
XCHG指令:交换数据
格式:XCHG R/M,R/M 两边不能同时为内存 数据宽度要一样
XCHG AL,CLXCHG DWORD PTR DS:[12FFC4],EAXXCHG BYTE PTR DS:[12FFC4],AL例:
MOV AL,1MOV CL,2XCHG AL,CL执行前:AL=1 CL=2
执行后:AL=2 CL=1
MOVS指令:移动数据 内存-内存
BYTE/WORD/DWORD
MOVS指令常用于复制字符串
MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] 简写为:MOVSBMOVS WORD PTR ES:[EDI],WORD PTR DS:[ESI] 简写为:MOVSWMOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI] 简写为:MOVSD例:
MOV EDI,12FFD8MOV ESI,12FFD0MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]执行后,EDI内存里的值被修改为ESI内存里的值,且EDI和ESI各加4
为什么各加4?
和DOWRD数据宽度相关,假如为WORD 则各加2
为什么执行完是加而不是减?
由DF(Direction Flag)方向标记位决定,当DF位为1时为减,当DF位为0时,则为加
STOS指令
将Al/AX/EAX的值存储到[EDI]指定的内存单元,和数据宽度相关
STOS BYTE PTR ES:[EDI] 将AL存储到[EDI]STOS WORD PTR ES:[EDI] 将AX存储到[EDI]STOS DWORD PTR ES:[EDI] 将EAX存储到[EDI]注意这里使用的是ES: 之前写的都是DS:
当背面为[EDI]时要使用ES: 这和背面要学的段寄存器有关,先记住
存储完数据后EDI地址的变化方向也受DF标记控制,1减0增
REP指令
按计数寄存器 (ECX) 中指定的次数重复执行指令
MOV ECX,10REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI] 也可以写成REP MOVSD这里的10为十六进制,也就是0x10=16
代码将会重复执行16次,会不会往同一个地方覆盖?
不会,因为每执行一次EDI和ESI都会变化4,变化方向由DF决定
来源:http://www.12558.net
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |