标志寄存器 EFL

EFL是32位寄存器
其中的每一位,含义都是不同的

0x00000246 16进制
0000 0000 0000 0000 0000 0010 0100 0110 二进制

第十位(从下标开始算 从右往左):DF位
DF位为``的时候: MOVS 执行完毕之后 ESI和EDI的值会增加
DF位位1的时候: MOVS 执行完毕之后 ESI和EDI的值会减少

修改标志寄存器中D位的值,然后在执行下面的指令

MOV EDI,12FFD8
MOV ESI,12FFD0
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]      观察EDI和ESI的值
MOV EAX,12345678
MOV EDI,12FFC4
STOS BYTE PTR ES:[EDI]                          观察EDI的值
STOS WORD PTR ES:[EDI]
STOS DWORD PTR ES:[EDI]

MOVS指令:移动数据 内存-内存

BYTE/WORD/DWORD

MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]   简写:MOVSB
MOVS WORD PTR ES:[EDI],BYTE PTR DS:[ESI]    简写:MOVSW
MOVS DWORD PTR ES:[EDI],BYTE PTR DS:[ESI]   简写:MOVSD  

例子:

MOV EDI,12FFD8
MOV ESI,12FFD0
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]      观察EDI的值

在汇编中,当我们需要把内存中的数据从一个地方复制到另一个地方的时候就会用到
EDI和ESI

ESI中存储需要复制的数据的内存地址,EDI是将要复制的地方

MOVS指令每执行一次,EDI和ESI的大小就自动增加或减少 取到内存中值的数据宽度大小
如果是 movs dword *** 那么每次就增加或减少4
如果是 movs word *** 那么每次就增加或减少2
如果是 movs byte ***那么每次就增加或减少1

STOS指令:AI/AX/EAX的值存储到[EDI]指定的内存单元

STOS BYTE PTR ES:[EDI]              简写: STOSB
STOS WORD PTR ES:[EDI]              简写: STOSW
STOS DWORD PTR ES:[EDI]             简写: STOSD

将寄存器EAX中的值放到EDI指定的内存中去

这里根据取不同的宽度所以取EAX中不同的位数
BYTE = AI
WORD = AX
DWORD = EAX

MOV EAX,12345678
MOV EDI,12FFC4
STOS BYTE PTR ES:[EDI]              观察EDI的值和EDI对应内存中的值
STOS WORD PTR ES:[EDI]
STOS DWORD PTR ES:[EDI]

STOS 每执行一次,EDI的值就自动增加或者减少
如果是 stos byte ... 那么每次就增加或减少1
如果是 stos word ... 那么每次就增加或减少2
如果是 stos dword ... 那么每次就增加或减少4

REP指令:按计数寄存器(ECX)中指定的次数重复执行字符串指令

上面的MOVS指令和STOS指令一次最多也只能移动4个字节,如果想移动大片的内存,那么就需要REP指令了

按计数寄存器(ECX)中指定的次数重复执行字符串指令,计数完毕后ECX会置零

MOVS ECX,0x10   ->16进制 "10" 对应10进制 16 也就是执行16次
REP MOVSD
MOVS ECX,0x10
REP STOSD

延伸

通用寄存器的通常用处:
EAX 通常用来作为返回值
ECX 通常用来作为计数器
ESP EBP 通常用来作为 堆栈的栈顶和栈低
ESI EDI 通常用做内存 复制的源地址和目标地址