antoniozhou的Blog

流媒体技术,服务器技术,多媒体网络应用

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

     NASM汇编器和MASM汇编器一样,都可以生成适用于Win32平台的coff文件格式,这种文件格式可以被MS 的link.exe连接器连接成PE文件。通常,我们知道MASM可以通过includelib伪指令将导入库的名称传给连接器link.exe,告知它该从哪个库中导入所需外部符号,而NASM汇编器在这方面的能力却是有过之而无不及,它可以通过info段,将更多的连接参数传递给link.exe,下面的两段代码展示了两者之间的用法和差异:

;filename: sayhellon.asm
;
;
cmd> nasm -fcoff -Xvc sayhellon.asm
;
cmd> link sayhellon.obj

extern _MessageBoxA@16    
;in user32.dll
extern _ExitProcess@4    ;in kernel32.dll

global SayHello
global _WinMain

[SECTION .drectve info align=
8]
    db 
" /subsystem:windows"
    db 
" /out:sayhellon.exe"
    db 
" /defaultlib:kernel32.lib"
    db 
" /defaultlib:user32.lib"
    db 
" /export:SayHello"
    db 
" /entry:WinMain"
    db 
" /merge:.rdata=.text",0

[SECTION .text USE32 align=
16]
szTitle:
    db 
"SayHello",0
szMsg: 
    db 
"Hello World!"0
SayHello:
    
push 0                ;uType
    push dword szTitle    ;lpCaption
    push dword szMsg      ;lpText
    push 0                ;hWnd
    call _MessageBoxA@16
    
ret 16    

_WinMain:
    
call SayHello
    
push 0
    
call _ExitProcess@4


     如上述代码所示,我基本上把link.exe连接器所需要的参数都写在源代码的.drectve段中了,注意:.drectve段由info标志,info是一种特殊的段,这个段只在coff文件中存在,link.exe连接器从这个段中读取控制指令参数,但是不会把这个段的内容写到生成的PE文件中。对info段的使用,MASM也用到了,只不过比较间接,比如对includelib的使用间接地使用info段,代码如下:

;filename:sayhellom.asm
;
cmd> ml /c /coff /nologo sayhellom.asm
;
cmd> link /subsystem:windows /libpath:\masm32\lib 
;
         /merge:.rdata=.text /export:SayHello /out:sayhellom.exe sayhellom.obj
;
    .586
    .model flat, stdcall
    option 
casemap:none
 
    include windows.
inc
    include kernel32.
inc
    include user32.
inc
 
    includelib kernel32.lib
    includelib user32.lib

    public c SayHello

.code
szTitle:
    db 
"SayHello",0
szMsg:
    db 
"Hello World!"0
SayHello PROC C
    
push MB_OK          ;uType
    push offset szTitle ;lpCaption
    push offset szMsg   ;lpText
    push 0              ;hWnd
    call [MessageBoxA]
    
ret 16
SayHello ENDP
 
start:
    
call SayHello
    
push 0
    
call [ExitProcess]
end start

 

     上述两种方法生成的EXE程序都是1kb大小,虽然效果相同,但NASM将参数写在源代码中,比较便于管理和生成,虽然可以通过Makefile文件管理生成步骤,但仍然会多一个Makefile文件,还要多用一个make.exe或nmake.exe,呵呵,这只是我的个人之见,毕竟MASM社区众多,资源丰富,譬如头文件、现成的宏定义等比较丰富,不过,有兴趣的读者仍然可以尝试一下NASM的这一特性。

     NASM还有一种更加方便的外部库函数导入方法,就是import伪指令,import伪指令可以直接使用函数名,而不用给函数名加上'_'前缀和'@number'后缀,但import伪指令仅适合于OMF(borland obj)格式输出,OMF格式是MS在16位下操作系统的目标文件格式,borland仍然使用这种格式,并将格式进行了扩展,使得可以在Win32环境下使用,NASM支持这种扩展的OMF格式,但必须显式指定生成32位的obj。由于import伪指令需要OMF格式的支持,而MS的link.exe连接器会在连接时自动将OMF格式转换成COFF格式,从而无法完成导入外部标志的操作,因此,需要一个直接支持连接OMF格式的连接器,这里推荐开源连接器alink.exe。alink.exe连接器将根据import伪指令生成的连接信息,找到所需动态库,并自动导入外部函数符号,代码如下:

;filename:sayhello.asm
;
cmd> nasm -fobj -Xvc sayhello.asm
;
cmd> alink -oPE -subsys windows sayhello.obj

import MessageBoxA user32.dll
extern MessageBoxA
import ExitProcess kernel32.dll
extern ExitProcess

global SayHello
export SayHello

[SECTION CODE USE32 CLASS=CODE]
szTitle:
    db 
"SayHello",0
szMsg: 
    db 
"Hello World!"0
SayHello:
    
push 0              ;uType
    push dword szTitle  ;lpCaption
    push dword szMsg    ;lpText
    push 0              ;hWnd
    call [MessageBoxA]
    
ret 16
 
..
start:
    
call SayHello
    
push 0
    
call [ExitProcess]

 

     上述代码段中的..start也是NASM针对OMF格式设计的程序入口简化标志,export伪指令生成的导出指令也将由alink.exe来执行。注意:alink.exe不支持段合并(至少我不知道如何使用alink.exe进行段合并>_<),因此,连接生成的EXE程序稍大一些,为2.51kb,有3个段,而上述另两种操作生成的EXE文件只有一个.text段。

posted on 2008-10-23 22:49  antoniozhou  阅读(7429)  评论(2编辑  收藏  举报