1.80386有三种工作模式:实模式、保护模式、虚拟86模式
复位加电时以实模式启动,只使用地址线的低20位,所有段都是可读可写可执行的,ring0,特权级
2.两个新寄存器用来管理段描述符表(记录所有段的属性和其他参数的表),一个是48位的GDTR,一个是16位的LDTR
GDTR指向的是全局描述符表GDT,唯一一个存在,直接指向内存地址,而LDTR指向局部描述符表LDT,只存放索引,指向局部描述符表内存段对应的描述符在全局描述符表中的位置
分页机制把4K大小的内存当做一页内存,每页物理内存可以根据页目录表+页表,随意映射到不同的线性地址上,从而实现物理地址不连续的内存映射在一起,线性连续
保护模式下,段选择子+偏移地址转换后的地址就是上述的“线性地址”,
是否启用内存分页机制由CR0的31位(PG位决定)
PG=0,则不启用分页,这时线性地址就是实际物理地址
PG=1,启用分页,线性地址要经过页表的映射才得到物理地址
3.win32汇编中不必去关心段寄存器,
4.movzx数据长度扩展,扩展的数据位全用0代替
byte data = 0x10; __asm { pushfd pushad MOVZX eax,data// EAX存放的是0X10,扩展位全为0 popad popfd }
5
leave:
mov esp,ebp
pop ebp
其实我们应该要注意到pop ebp时,esp也加了4.
6
MOVZX 指令
格式: MOVZX OPD,OPS
----
功能: 总是高位0扩展
注意点:不要再写成
bTest1 byte 12h movzx ax, word ptr bTest1 (位数相同,所以没必要扩展?)也
也就是不要再做强制转换了,否则报错,
应该写成
movzx ax, bTest1
而且我发现写成 movzx al,bTest1(位数相同,所以没必要扩展?)也报错,
估计意思就是只有在需要扩展时才能用这个,
MOVSX同样有这问题.
7.
条件测试语句只是简单的把每个表达式翻译成cmp或test指令,所以存在限制:
表达式的左边只能是变量或寄存器,不能是常数,
表达式的两边不能同进为变量,但可以同时是寄存器.
8.自己分析一段条件测试句的反汇编:
00404017 0BC0 or eax, eax 00404019 74 04 je short 0040401F 0040401B 3BDF cmp ebx, edi 0040401D 73 04 jnb short 00404023 0040401F 3BF1 cmp esi, ecx 00404021 75 07 jnz short 0040402A 00404023 BE 01000000 mov esi, 1 00404028 EB 18 jmp short 00404042
0040402A 0BD2 or edx, edx0040402C 74 07 je short 004040350040402E BE 02000000 mov esi, 200404033 EB 0D jmp short 0040404200404035 F7C6 01000000 test esi, 10040403B 74 05 je short 004040420040403D BE 03000000 mov esi, 300404042 0000 add byte ptr [eax], al
自己分析的,以后说不定有更好的方法,首先都有个jmp short 00404042,所以很明显,00404042应该是整个条件分支的未句了,
以此分为三段,由于它们都jmp short 00404042,说明应该是if.else if 这样,自上而下,一个条件成立,执行相应代码,然后就跳过其他代码:第一段:
00404017 0BC0 or eax, eax 00404019 74 04 je short 0040401F 0040401B 3BDF cmp ebx, edi 0040401D 73 04 jnb short 00404023 0040401F 3BF1 cmp esi, ecx 00404021 75 07 jnz short 0040402A 00404023 BE 01000000 mov esi, 1 00404028 EB 18 jmp short 00404042 第二段:
0040402A 0BD2 or edx, edx 0040402C 74 07 je short 00404035 0040402E BE 02000000 mov esi, 2 00404033 EB 0D jmp short 00404042 第三段:
00404035 F7C6 01000000 test esi, 1 0040403B 74 05 je short 00404042 0040403D BE 03000000 mov esi, 3
先分析第一段:
内部又有三个jmp语句,je short 0040401F和jnb short 00404023和jnz short 0040402A,仔细看,发现0040402A指向第二段了,这应该说明这个条件成立就直接跳到第二段,而不执行第一段内容了,而0040401F指向第一段内部,00404023执行第一段内容,我先把这三个条件都提出来吧:
1.eax大小判断
2.ebx>=edi
3.esi == ecx
4.内容:mov esi,2
它们之间存在的关系:
1>eax==0,则跳到3,eax!=0,则继续2
2>ebx>=edi,则执行内容4,否则继续3
所以写出表达式应该是if(eax && ebx>=edi)|| (esi == ecx)
mov esi,2
同样第二段分析就是:else if(edx)
mov esi,2
第三段为 else if (esi & 1)
mov esi, 3
分析完成.
9.使用条件分支伪指令时,总是把操作数当作无符号数看待,这时,假定eax为1,那么表达式eax>-1的值是假,因为-1表示为offffffffh,如果当做无符号数看,它反而是最大的数.
10.汇编中,window内部将这ebx, edi, esi,ebp当做指针来使用,如果返回时改变了它们的值,程序马上会崩溃,所以以定要保存它们,
可以用proc stdcall uses ebx edi esi或直接pushad--popad
11.window在处理Sendmessage的时候要检查消息的类型,如果参数是一个指针,window首先创建一块共享内存,并将指针指向的字符串拷贝到该内存中,然后再发送消息到其他进程,并将共享内存在目标进程中的地址发送给目标窗口过程,目标窗口过程处理完消息后,函数返回,共享内存被释放,所以消息传到目标窗口过程时,指针的取值会有所变化,但它指向的字符是正确的,在用户自定义的消息中(WM_USER+...),不要在消息参数中传递指针,这会引发非法访问内存,因为window不知道用户的意图,它只会把lp和wp当两个普通的数值传递,而不会帮用户把指针指向的内容复制到一块共享内存中