背景知识
一.80x86处理器的三种工作模式:实模式,保护模式,虚拟86模式。
1.三种模式的关系
2.三种模式的各自特点(寻址空间,内存使用,寄存器的使用,优先级,中断保护,特权指令等)
二.Windows的内存管理
1.Win32汇编中每一个程序都可以使用4G的内存么?
2.Win32汇编代码中为什么看不到CS,DS,ES和SS等段寄存器呢?
3.DOS下的著名的“640KB限制”是什么?
三.80386的内存分页机制
1.在保护模式下,段选择器+偏移地址被称作线形地址,那么线形地址就是物理地址么?
2.虚拟内存的实现。
3.Windows操作系统为用户程序的代码段,数据段和堆栈段都已经设置好了正确的描述符,用户因此不必关心段寄存器。
四.Windows的特权保护
1.80386的异常和中断处理。
为什么在win32编程中没有int指令?其实调用API就是中断处理了。
2.80386的保护机制
A.段的类型检查。可读可写可执行方面
B.页的类型检查。可读可写方面
C.访问数据时的级别检查。访问优先级
D.控制转移的检查。优先级问题
E.指令集的检查。特权指令和敏感指令
F.I/O操作的保护。
编程环境
一. 刀和枪
代码编写工具:MASM32软件包和ASM FOR EDITPLUS
资源编辑器:VC的资源编辑器
二. Ml.exe,Link.exe和nmake的用法
三. 设置环境变量的批处理文件
@echo off
Set include=x:\masm32\Include
Set lib=x:\masm32\lib
Set path=x:\masm32\bin;%path%
Echo on
了解WIN32汇编程序结构
一. 模式定义:
.386 //指令集
.model flat,stacall //模式
option casemap:none //格式
二. 段的定义:在WIN32汇编中有以下几个段供使用
数据段
.data 已定义的数据变量
.data? 未定义的数据变量(可以视情况分配空间,节约程序大小)
.const 常量
代码段
.code
三. 程序的结束和入口地址
说来惭愧,还记得张驴儿在我开始学习WIN32汇编的时候曾经问我:“在Windows汇编程序设计中也有main()函数么?”我不以为然的回答:“是啊”。现在想想真是寒啊。自己不懂就多学习嘛还楞是装~!
其实在WIN32汇编中不存在C语言中的main()函数,在C中编译器是默认的把main()函数当作程序的入口地址并执行。但是在汇编中这种情况没有了,你需要自己指定入口地址,这是由程序中最后一句:end start来完成的。End后面的标识符就是程序的入口地址!
四. 注释和换行
一个作风严格的程序员是要有好的习惯的。
汇编源程序中的注释是以“;”开始的。
当一行还显示不下源程序的代码时,用“\”表示换行。
附:一个简单的HELLO WORLD!程序
.386
.model flat
Option casemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;Include文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Include windows.inc
Include user32.inc
Includelib user32.lib
Include kernel32.inc
Includelib kernel32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data
szCaption db ‘A MessageBox!’,0
szText db ‘HELLO WORLD!’,0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
Start:
Invoke MessageBox,NULL,offset szText,offset szCaption,MB_OK
Invoke ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
End start
五. 调用API
使用invoke。Invoke伪指令不是386的处理指令,而是MASM编译器的伪指令。API函数有的有返回值,返回值类型对于汇编程序来说只有一种:dword,它永远放在eax中。
与字符串相关的API函数有两种:一类是处理ANSI字符集的,一类是处理UNICODE字符集的。
标号、变量和数据结构
一. 标号:当程序中要跳转到另一个位置的时候,需要有一个标识来指示新的位置,这就是标号。通过在目的地址前面放一个标号,可以在指令中使用标号来代替直接使用地址。@@的使用
二. 全局变量和局部变量:全局变量放在.data和.data?中。局部变量的使用有利于大工程中的程序模块封装。局部变量放在堆栈中。MASM中用local伪指令提供对局部变量的支持。RtlZeroMemory这个API函数对局部变量实行初始化。
三. 数据结构:assume伪指令把寄存器预先定义为结构指针。
Mov esi,offset stWndClass
Assume esi
tr WNDCLASSMov eax,[esi].lpfnWndProc
…
Assume esi:nothing
四.获取变量的地址。全局变量:offset伪指令;局部变量:lea,注:在invoke中使用局部变量的地址要用addr!而且addr指令只能用在invoke中。而且不能在addr前使