《Windows环境下32位汇编语言程序设计》 第三章笔记

本文详细介绍了Windows 32位汇编语言的编程模式,包括内存模型、代码段、数据段、堆栈段的定义,以及如何调用API函数和定义子程序。讲解了invoke语句的使用、函数声明、全局和局部变量的定义,并探讨了不同语言调用约定的差异。此外,还提到了汇编语言中条件和循环语句的语法。

模式定义

.386
.model flat,stdcall
option casemap:none
  • .386语句是汇编语言的伪指令,用于告诉编译器在本程序中使用的指令集。
  • .model语句用来定义程序工作的模式,它的用法是:.mode 内存模式 [,语言模式] [,其他模式]
内存模式
模式内存使用方式
tiny用来建立 .com文件,所有的代码、数据和堆栈都在同一个64KB段内
small建立代码和数据分别用一个64KB段的 .exe文件
medium代码段可以有多个64KB段,数据段只有一个64KB段
compact代码段只有一个64KB段,数据段可以有多个64KB段
large代码段和数据段都可以有多个64KB段
huge同large,并且数据段中的一个数组也可以超过64KB
flatWin32程序使用的模式,代码和数据段使用同一个4GB段
  • option语句定义的选项有很多,在win32汇编程序中,需要的只是定义option casemap:none,这个语句定义了程序中的变量和子程序名是否对大小写敏感,由于Win32 API名称是区分大小写的,所以必须指定这个选项,否则在调用API的时候会有问题

段的定义

数据段

  • .data,.data?和.const定义的是数据段,分别对应不同方式的数据定义,在最后生成的可执行文件中也分别放在不同的节区(Section)中。程序中的数据定义一般可以归纳为3类
    1. 可读可写的已定义变量。这些数据在源程序中已经被定义了初始值,而且在程序的执行中有可能被更改,如一些标志等,这些数据必须定义在.data段中,.data段一般存放在可执行文件的_DATA节区内。
    2. 可读可写的未定义变量。这些变量一般是当做缓冲区或者在程序执行后才开始使用的。这些数据可以定义在.data段中,也可以定义在.data?段中,但一般把它放到.data?段中。虽然定义在这两种段中都可以正常使用,但定义在.data?段中不会增大.exe文件的大小。
      3.可读不可写的常量。如一些要显示的字符串信息,他们在程序装入的时候已经有效,在整个执行过程中不需要修改,这些数据可以放在 .const段中, .const段是常量段,它是可读不可写的

代码段

  • .code段是代码段,所有的指令都必须写在代码段中,在可执行文件中,代码段一般是放在_TEXT节区中的,Win32环境中的数据段是不可执行的,只有代码段的属性。对于工作在特权级3的应用程序来说,.code段是不可写的。

堆栈段

  • 在程序中不必定义堆栈段,系统会自动分配堆栈空间。堆栈段的内存属性是可读可写可执行的。

调用API

使用invoke语句

invoke 函数名 [,参数1] [,参数2]......

函数的声明

在调用API函数的时候,函数原型也必须预先声明,否则,编译器会不认这个函数。invoke伪指令也无法检查参数个数。声明函数的格式是:
函数名 proto [距离] [语言] [参数1]:数据类型, [参数2]:数据类型,......

  • proto是函数声明的伪指令
  • 距离 可以是NEAR,FAR,NEAR16,NEAR32,FAR16或FAR32,Win32只有一个平坦的段,无所谓距离,所以在定义时是忽略的
  • 语言类型就是 .model那些类型,如果忽略,则使用.model定义的默认值
  • 参数,由于Win32 API仅仅使用了dword类型的参数,所以绝大多数的数据类型都是doword。

include语句

  • 在Win32汇编中使用API函数,程序必须知道调用的API函数存在于哪个DLL中,否则操作系统必须搜索系统中存在的所有DLL,并且无法处理不同DLL中的同名函数,所以必须有个文件包括DLL库正确的定位信息,这个任务是由导入库来实现的。

includelib 库文件名includelib <库文件名>

全局变量

全局变量的定义

Win32汇编的全局变量定义在.data或.data?段内,可以同时定义变量的类型和长度:
变量名 类型 初始值1,初始值2,......
变量名 类型 重复数量 dup (初始值1,初始值2,......)

变量的类型
名称表示方式缩写长度(字节)
字节bytedb1
worddw2
双字dworddd4
三字fworddf6
四字qworddq8
十字节BCD码tbytedt10
有符号字节sbyte1
有符号字sword2
有符号双字sdword4
单精度浮点数real44
双精度浮点数real88
10字节浮点数real1010

局部变量的定义

local 变量1[[重复数量]] [:类型],变量2[[重复数量]] [:类型]......

  • local伪指令必须紧接在子程序定义的伪指令proc后,数据类型不能缩写,默认的类型是dword。局部变量的作用域是当前的子程序。

子程序的定义

子程序名 proc [距离] [语言类型] [可视区域] [USES 寄存器列表] [,参数:类型] ......[VARARG]
        local 局部变量列表
        
        程序

子程序名 endp
  • 距离——可以是NEAR,FAR等,win32中只有一个平坦的段,所以对距离的定义忽略
  • 语言类型——表示参数的使用方式和堆栈平衡的方式,如果忽略,则使用程序头部.mode定义的值
  • 可视区域——可以是PRIVATE,PUBLIC和EXPORT。PRIVATE表示子程序只对本模块可见;PUBLIC表示对所有的模块可见(在最后编译链接完成的.exe文件中);EXPORT表示是导出函数,当编写DLL的时候要将某个函数导出的时候可以这样使用。默认的设置是PUBLIC。
  • USES寄存器列表——表示由编译器在子程序指令开始前自动安排push这些寄存器指令,并且在ret前自动安排pop指令,用于保存执行环境。
  • 参数——参数指参数的名称,在定义参数名的时候不能跟全局变量和子程序中的局部变量重名。
  • 类型——由于win32中的参数类型只有32位(dword)一种类型,所以可以忽略。
  • VARARG——表示在已确定的参数后还可以跟多个数量不确定的参数,在Win32汇编中唯一使用VARARG的API就是wsprintf。
不同语言调用方式的差别
CSysCallStdCallBASICFORTRANPASCAL
最先入栈参数
清除堆栈者调用者子程序子程序子程序子程序子程序
最先入栈参数

分支语句

.if 条件表达式1
 	表达式1为“真”时执行的指令
[.elseif 条件表达式2]
 	表达式2为“真”时执行的指令
[.elseif 条件表达式3]
 	表达式3为“真”时执行的指令
.....
[.else]
	所有表达式为“否”时执行的指令
.endif

循环语句

.while 条件测试表达式
	指令
	[.break [.if 退出条件]]
	[.continue]
.endw
或
.repeat
	指令
	[.break [.if 退出条件]]
	[.continue]
	.until 条件测试表达式 (或.untilcxz [条件测试表达式1]

使用标号@@

  • 当@@做标号时,可以用@F和@B来引用它,@F表示本指令后的第一个@@标号,@B表示本指令前的第一个@@标号,程序中可以有多个@@标号,但是@B和@F只寻找匹配最近的一个。
××××××××××××××××××××××××××× × 《Windows环境32汇编语言程序设计》 × × 附书代码说明 × ××××××××××××××××××××××××××× 1. 编译器和链接器 本附书代码全部采用 MASM 格式编写,推荐使用 MASM32 软 件包作为编译环境,MASM32 软件包可以在以下地址下载: MASM32官方站点: http://www.masm32.com 安装及开发的操作系统建议采用32Windows 7,在64操作系统 上安装 MASM32 软件包,安装生成的Lib文件可能不兼容。 安装完成以后请将本光盘根目录下的环境设置批处理文件Var.bat 拷贝到 Masm32\bin 目录下,并根据 MASM32 的安装置编辑修改 Var.bat 文件中的相关目录名称。 2. 代码维护工具 每个例子都包括了描述编译、链接方法的 makefile 文件, 使用 nmake 工具可以自动根据此文件进行编译链接,nmake 工 具可以从 Visual C++ 的 bin 目录中找到,也可以从作者的网 站中下载。 3. 编译环境和编译方法 建议使用命令行方式进行编译,以编译 Chapter02\Test 目录中 Test.asm 为例,步骤是: I. 打开一个“命令提示符”窗口。 II. 进入环境设置批处理文件 Var.bat 所在目录并执行 它,以后就可以使用这个“命令提示符”窗口编译 文件了。 x: cd \masm32\bin var III. 进入源代码目录: cd \chapter02\test IV. 使用 nmake 工具进行编译链接: nmake V. 执行编译好的可执行文件。 如果需要对源代码进行修改,不必关闭“命令提示符”窗口, 只要切换到编辑器窗口,在修改 *.asm 文件后重复进行第 IV 和 第 V 步骤即可。 # 特别注意:将光盘中的代码拷贝到硬盘后,必须将文件的只读属性去除! 4. 本光盘所包含目录的说明 根目录下的 *.pdf ;附录A、B、C的电子版文档 Chapter02\Test ;测试编译环境 Chapter03\HelloWorld ;Hello World Chapter04\FirstWindow ;用Win32汇编写第一个窗口 Chapter04\FirstWindow-1 ;用Win32汇编写第一个窗口 Chapter04\SendMessage ;窗口间的消息互发 Chapter04\SendMessage-1 ;窗口间的消息互发 Chapter05\Menu ;使用资源 - 使用菜单 Chapter05\Icon ;使用资源 - 使用图标 Chapter05\Dialog ;使用资源 - 使用对话框 Chapter05\Listbox ;使用资源 - 使用列表框 Chapter05\Control ;使用资源 - 使用子窗口控件 Chapter05\ShowVersionInfo ;使用资源 - 显示版本信息资源的程序 Chapter05\VersionInfo ;使用资源 - 使用版本信息资源 Chapter06\Timer ;定时器的使用 Chapter07\DcCopy ;在两个窗口的 DC 间互相拷贝屏幕 Chapter07\Clock ;模拟时钟程序 Chapter07\BmpClock ;用 Bitmap 图片做背景的模拟时钟程序 Chapter07\TestObject ;一些常见的绘图操作 Chapter08\CommDlg ;使用通用对话框 Chapter09\Toolbar ;使用工具栏 Chapter09\StatusBar ;使用状态栏 Chapter09\Richedit ;使用丰富编辑控件 Chapter09\Wordpad ;一个完整的文本编辑器例子 Chapter09\SubClass ;窗口的子类化例子 Chapter09\SuperClass ;窗口的超类化例子 Chapter10\MemInfo ;显示当前内存的使用情况 Chapter10\FindFile ;全盘查找文件的例子 Chapter10\FormatText ;文件读写例子 Chapter10\FormatText\FileMap ;使用内存映射文件进行文件读写的例子 Chapter10\MMFShare ;使用内存映射文件进行进程间数据共享 Chapter11\Dll\Dll ;最简单的动态链接库例子 - 编写 DLL Chapter11\Dll\MASM Sample ;最简单的动态链接库例子 - 使用 DLL Chapter11\Dll\VC++ Sample ;最简单的动态链接库例子 - 在VC++中使用汇编编写的DLL Chapter11\KeyHook ;Windows 钩子的例子 - 监听键盘动作 Chapter11\RecHook ;Windows 日志记录钩子的例子 - 监听键盘动作 Chapter12\Counter ;有问题的程序 - 一个计数程序 Chapter12\Thread ;用多线程的方式解决上一个程序的问题 Chapter12\Event ;使用事件对象 Chapter12\ThreadSynErr ;一个存在同步问题的多线程程序 Chapter12\ThreadSyn\UseCriticalSection ;使用临界区对象解决多线程同步问题 Chapter12\ThreadSyn\UseEvent ;使用事件对象解决多线程同步问题 Chapter12\ThreadSyn\UseMutex ;使用互斥对象解决多线程同步问题 Chapter12\ThreadSyn\UseSemaphore ;使用信号灯对象解决多线程同步问题 Chapter13\CmdLine ;使用命令行参数 Chapter13\Process ;创建进程的例子 Chapter13\ProcessList ;显示系统中运行的进程列表 Chapter13\Patch1 ;一个内存补丁程序 Chapter13\Patch2 ;一个内存补丁程序 Chapter13\Patch3 ;一个内存补丁程序 Chapter13\HideProcess9x ;Windows 9x下的进程隐藏 Chapter13\RemoteThreadDll ;用 DLL 注入的方法实现远程进程 Chapter13\RemoteThread ;不依靠任何外部文件实现远程进程 Chapter14\TopHandler ;使用筛选器处理异常 Chapter14\SEH01 ;最基本结构化异常处理例子 Chapter14\SEH02 ;改进后的结构化异常处理例子 Chapter14\Unwind ;异常处理中的展开操作例子 Chapter15\Ini ;使用 INI 文件 Chapter15\Reg ;操作注册表的例子 Chapter15\Associate ;操作注册表实现文件关联 Chapter16\TcpEcho ;实现 TCP 服务器端的简单例子 Chapter16\Chat-TCP ;用 TCP 协议实现的聊天室例子 Chapter17\PeInfo ;查看 PE 文件的基本信息 Chapter17\Import ;查看 PE 文件的导入表 Chapter17\Export ;查看 PE 文件的导出表 Chapter17\Resource ;查看 PE 文件的资源列表 Chapter17\Reloc ;查看 PE 文件的重定信息 Chapter17\NoImport ;不使用导入表调用 API 函数 Chapter17\AddCode ;在 PE 文件上附加可执行代码的例子 Chapter18\OdbcSample ;用ODBC操作数据库的例子 Appendix A\EchoLine ;控制台输入输出的例子 Appendix B\MsgWindow01 ;消息机制试验 1 Appendix B\MsgWindow02 ;消息机制试验 2 Appendix B\MsgWindow03 ;消息机制试验 3 Appendix B\MsgWindow04 ;消息机制试验 4 Appendix C\BrowseFolder ;浏览目录对话框 6. 联系作者 虽然本书中所有的例子代码都已经在32Windows 98、Windows 2000、 Windows XP、Windows Vista和Windows 7下测试通过,但也有存在Bug的可能,如果 发现代码存在错误或者有其它问题,请告知作者,联系方法: E-mail:luoyunbin@hotmail.com 感谢您的支持! 作者:罗云彬
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值