0000.0001.0010.0011.0100.0101.0110.0111.1000.1001.1010.1011.1100.1101.1110.1111 0 1 2 3 4 5 6 7 8 9 A B C D E F
8位寄存器:AL CL DL BL AH CH DH BH 16位寄存器:AX CX DX BX SP BP SI DI 32位寄存器:EAX ECX EDX EBX ESP EBP ESI EDI
CF位 无符号数运算,1表示进位,借位,溢出 不然就为0 OF位 有符号数运算,1表示进位,借位,溢出 不然就为0 PF位 奇偶数校验,最后一个字节的1的个数为奇数就为0,为偶数就为1 AF位 算数操作结果的第3位发生进为或借位,就为1,别的情况就为0 ZF位 结果为0,ZF位就为1,可以和CMP或者TEST或者一些指令一起使用,比如:判断两个值是否相等时就可以用 SF位 结果为正就为0,负就为1 DF位 方向标识位,地址从高到低执行,还是低到高执行,会受DF位影响
EAX FFFF 0001 整体就是32位,一半就是16,再一半8 还有分高低位,例如这里8位的 00 就是AH高8位,01就是AL低8位 所以要修改00就可以指定AH mov ah,3
CMP EAX,ECX 和sub减法一样,就是结果不会存到EAX,但是会改变一些寄存器,比如 ZF位 TEST EAX,ECX 和and一样,就是结果不会存在EAX,但是会改变一些寄存器,比如 ZF位 ----------------- mov 寄存器,值 向寄存器 存一个值 例:mov EAX,1 向EAX寄存器存入1
mov EDX,EAX 把寄存器的值存入另一个寄存器 注意寄存器宽度要一样的
WORD 16位 DWORD 32位 所有运算都可以是寄存器和内存地址,只要数据宽度相同 结果都是存到前面那个位置
-----------------基本的运算----------------- MOV DWORD PTR DS:[18FF94],EAX 语法:MOV 数据宽度 PTR DS:[18FF94],数据宽度相同的寄存器 存入内存地址,EAX寄存器的值写入18FF94内存地址 ADD EAX,ECX 相加,EAX的值加上ECX的值,写入到EAX SUB AL,BYTE PTR DS:[18FFA0] 相减,减多少的值可以是寄存器,也可以是内存地址的值 AND DWORD PTR DS:[18FFA0],EAX 与运算 OR DWORD PTR DS:[18FFA0],EAX 或运算 XOR DWORD PTR DS:[18FFA0],EAX 异或^,结果不一样的位是1,一样的位是0 NOT 寄存器/内存 反转结果
-----------------移动数据:内存到内存----------------- ESI 指定源地址 EDI 指定目标
寄存器 EFL 00000246 拆为二进制 0000 0000 0000 0000 0010 0100 0110 右边从0开始算的第十位DF位 是0的话,用完MOVS指令ESI和EDI就会+1或+2或+4,取决于你MOVS几字节 是1的话就 -1 -2 -4
ESI 0018FF8D EDI 0018FFA1 MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] 把 ESI 内存地址的值复制到了 EDI 内存地址 每运行一次 ESI 内存地址和 EDI 内存地址会自加 这里一次复制一个字节所以每次加1 内存地址变成为: ESI 0018FF8E EDI 0018FFA2
指令简写: MOVSB 相当于MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] ,复制一个字节 MOVSW 二个字节 MOVSD 四个字节
-----------------移动数据:寄存器到内存----------------- STOS BYTE PTR ES:[EDI] AL寄存器的值存储到EDI指定的内存地址 STOS WORD PTR ES:[EDI] AX寄存器的值存储到EDI指定的内存地址 STOS DWORD PTR ES:[EDI] EAX寄存器的值存储到EDI指定的内存地址 EDI的值也会和上面一样发生改变,+1 +2 +4 -1 -2 -4 取决于寄存器 EFL的D位和你存储多少字节
指令简写: STOSB STOSW STOSD
-----------------重复执行指令(循环指令)----------------- ECX 寄存器相当于计数器,执行一次减一,存的是16进制的值所以一个F执行15次
MOV ECX,10 修改计数器的值为十六进制的10,执行16次 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI] 循环MOVS指令 指令简写: REP MOVSD REP STOSD
----------------- 堆栈 ----------------- 堆栈:系统分配好的 专门给程序用的
FS 7EFDD000 堆栈地址
ESP 堆栈指针寄存器 记录堆栈用到哪了,大地址开始用,超出范围 = 堆栈溢出
----------------- 堆栈源地址修改----------------- SUB ESP,8 减少堆栈内存4字节,使他跳过两内存地址 不修改那两内存地址,直接跳过那4字节的内存地址 修改下一位内存地址 ADD ESP,8 堆栈使用到的内存地址+8(加四字节)
!!!出入几个字节 下一位源地址就减几位或加几位 ----------------- 入栈,写入值到栈里----------------- PUSH EAX 写入4字节的数据到堆栈(ESP)指定的源地址,然后堆栈(ESP)指定的源地址加4字节(下一位写入位置) 写入EAX到当前栈指针源地址,堆栈源地址到下一位 写入字节不同,堆栈源地址也会随着改变 PUSH DWORD PTR DS:[18FFA4] 内存地址的值写入当前堆栈(ESP)指定的源地址 PUSH 8 写入一个立即数
----------------- 出栈,栈的值赋值到别的地方----------------- POP ECX 当前栈源地址的值,赋值给ECX寄存器,然后+4字节,就是到上一位 等下次写入的时候,就会覆取出值存到ECX寄存器的那个内存地址 POP [18FFA4] 一样可以用内存地址,或寄存器
----------------- CPU下次执行的位置 ----------------- EIP 寄存器 cpu下次执行的内存地址内的指令
----------------- JMP修改EIP 堆栈(ESP)不会发生改变 ----------------- JMP 004183F4 修改EIP的值 JMP EAX EIP寄存器写入EAX寄存器的值 JMP DWORD PTR DS:[0018FFB8] 内存地址的 值 写入EIP ----------------- 修改EIP 堆栈发生改变 ----------------- 修改EIP 并把下一行内存地址写入堆栈中,所以发生改变 CALL 004183F4 把004183F4的值写入EIP,再把下一个内存地址写入堆栈(ESP)指定的源地址中 004183F4的值写到了EIP然后下一个内存地址(004183F5)写到了堆栈当前指定的源地址
----------------- 堆栈的值 写到EIP ----------------- RETN 当前堆栈内存地址的值写到EIP 并且地址位置+4(到上一位) 可以用在函数,比如CALL调用了函数,然后函数结尾用ret就能回到CALL下一行了
----------------- 堆栈值做为参数 ----------------- MOV EAX,DWORD PTR DS:[ESP+4] ESP上一位的值写入到EAX
----------------- JCC指令(判断指令)----------------- 相当于if,谁跟谁判断,比如用的JE就是判断ZF位为1还是0
JE SHORT ipmsg.004183F8 JE是看ZF位,比如这条指令执行的时候 ZF位为0的时候就不会修改EIP ZF位为1的时候就会修改EIP 还有很多 比如JG啊 SF位=0F 且 ZF=0就执行命令,不然就跳过这条指令
