前段时间发了两篇nasm-win32汇编的文章,看到有一些朋友很有兴趣,也在讨论nasm和fasm,masm孰优孰劣,其实这些都是工具而已,如果可以用好其中任何一个我想都可以做成大事的!至于是否用应该用汇编写Win32的GUI程序,我想用汇编先写GUI程序也是学习的需要,先写GUI程序树立起汇编绝对可以应对现代开发的需要的信心,而且用起来也很不是很复杂,这样学习者才不至于望而却步,然后再深入到汇编的精髓,同时也可以加深对操作系统的理解。
    在这里我还是要继续介绍NASM了,因为我很喜欢这款汇编编译器,正所谓已所不欲,勿施于人,我也希望能有更多的朋友可以喜欢这款编译器。为了更好地向大家介绍NASM我打算把自己的学习笔记做成一个系列,拿出来给大家晒晒,今天就先来点基本概念。

   今天开始正式win32汇编的学习,我采用用的编译器是nasm(The Netwide Assembler),因为它是开源的,学习过它的语法后可以同时编写win和Linux程序。纯属个人爱好,不过nasm的资料是少之又少,能找到的也只有两套,一个是nasm的用户手册,另一个是由Paul Carter用nasm语法写的汇编教程pcasm,大家在学习的过程中可以参考这两套教程。由于nasm在设计之初就本着可移植和语法简洁易懂的原则,因此它的的伪指令比较少,但是它提供了强大的宏支持。因为nasm编译器本身并没有提供win32的头文件,和一些必要的高级特性,因此我进一步选择了nasmx作为作为编译环境。nasmx是一个开源项目,它提供了开发win32和Linux甚至XBOX的相关头文件和用宏实现的高级特性,而且还包括实例程序,链接程序,资源管理程序等,都是一些开源的软件。以后我就以nasmx为基础介绍win32汇编。

    首先介绍一下nasmx的基本书写格式

%include '头文件地址'

entry 入口点

[section 段名]  

[section 段名]

[section 段名]

    %include是nasm里的标准宏,用来引用外部文件。entry是在nasmx里定义的一个宏,用来指定程序的入口点,提高了程序的可读性。nasm在编译的时候提供了多种输出目标文件格式,包括微软OMF格式和win32格式。在使用“nasm -fwin32 源程序.asm -o 目标程序.obj”命令进行编译时,nasm提供了标准的段名:“.text”,“code”“.data”,“.bss”,“rdata”,“align”,“”段名的类型和属性是由nasm自动产生的。“.text”或“code”把一个段定义为代码段,这个段可读并可执行,但是不能写。“.data”和“.bss”定义数据段,数据段可读可写,但不可执行,“.data”定义为一个被初始化的数据段,“.bss”定义为一个未初始化的数据段。“align”跟上一个数字,给出段的对齐长度。最大可以指定为64。在缺省情况下nasm设定的各段属性为:
section .text  code  align=16
section .data  data  align=4
section .bss   bss   align=4

理论:
    win32程序运行在保护模式下,保护模式的历史可以追溯到80286.而今80286已成为了历史。所以我们将只把精力集中于80386及后续的X86系统CPU。Windows把每一个Win32应用程序放到分开的虚拟地址空间中去运行,也就是说每一个程序都拥有相互独立的4GB地址空间,当然这倒不是说它们都拥有4GB的物理地址空间,而只是说能够在4GB的范围内寻址。操作系统将会在应用程序运行时完成4GB的虚拟地址和物理内存地址间的转换。这就要求编写应用程序时必须恪守Windows的规范,否则极易引起内存的保护模式错误。
    win32下只有一种内存模式,即FLAT模式,意思是“平坦”的内存模式,所有的win32的应用程序运行在一个连续、平坦、巨大的4GB的空间中。这同时也意味着你无须和段寄存器打交道,你可以用任意的段寄存器寻址任意的地址空间,这对于程序员来说是非常方便的,这也使得用32位汇编语言和用C语言一样方便。在win32下编程,有许多重要的规则需要遵守。有一条很重要的是:Windows在内部频繁使用ESI,EDI,EBP,EBX寄存器,而且并不去检测这些寄存器的值 是否被更改,这样当你要使用这些寄存器时必须先保存它们的值,待用完后恢复它们,一个最显著的例子就是Windows的CallBack函数中。

参考书目:《Iczelion的Win32汇编教程》  ,感谢本书的作者和译者们!