一、OMF文件格式链接:使用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伪指令生成的连接信息,找到所需动态库,并自动导入外部函数符号。..start也是NASM针对OMF格式设计的程序入口简化标志,export伪指令生成的导出指令也将由alink.exe来执行。注意:alink.exe不支持段合并(至少我不知道如何使用alink.exe进行段合并>_<),因此,连接生成的EXE程序稍大一些,为2.51kb,有3个段,而上述另两种操作生成的EXE文件只有一个.text段。
1、32位程序例子:
;filename:obj32.asm
import MessageBoxA user32.dll
extern MessageBoxA
import ExitProcess kernel32.dll
extern ExitProcess
global obj32
export obj32
[SECTION CODE USE32 CLASS=CODE]
szTitle:
db "SayHello",0
szMsg:
db "Hello World!", 0
obj32:
push 0 ;uType
push dword szTitle ;lpCaption
push dword szMsg ;lpText
push 0 ;hWnd
call [MessageBoxA]
ret 16
..start:
call obj32
push 0
call [ExitProcess]
使用alink。
cmd> nasm -fobj obj32.asm
cmd> alink -oPE obj32.obj
2、16位程序例子:
;filename:obj16.asm
segment code use16
str1: db "name$"
segment data use16
..start:
mov ax,code
mov ds,ax
mov dx,str1
mov ah,9
int 21h
mov ah,4ch
int 21h
使用alink。
cmd> nasm -fobj obj16.asm
cmd> alink obj16.obj 或alink -oEXE obj16.obj
二、微软Win32平台的coff文件格式链接:这种文件格式可以被MS的link.exe连接器连接成PE文件。通常,我们知道MASM可以通过includelib伪指令将导入库的名称传给连接器link.exe,告知它该从哪个库中导入所需外部符号,而NASM汇编器在这方面的能力却是有过之而无不及,它可以通过info段,将更多的连接参数传递给link.exe,链接时要加入口名。link.exe连接器所需要的参数都写在源代码的.drectve段中了,注意:.drectve段由info标志,info是一种特殊的段,这个段只在coff文件中存在,link.exe连接器从这个段中读取控制指令参数,但是不会把这个段的内容写到生成的PE文件中。对info段的使用,MASM也用到了,只不过比较间接,比如对includelib的使用间接地使用info段。
1、使用微软link.exe与kernel32.lib、user32.lib。例子如下:
;filename: win32sam.asm
extern __imp__MessageBoxA@16 ;in user32.dll 注解:可改为__imp__MessageBoxA@16(使用微软的库)或__imp_MessageBoxA@16(或MessageBoxA使用win32.lib库,使用什么外部名,要与链接库里的名称相符,nasm不会对外部符号进行增加东西,ml编译器在编译时则会对外部符号加_与@**。
extern _ExitProcess@4 ;in kernel32.dll
global SayHello
global _main
[SECTION .drectve info align=8]
db " /subsystem:windows"
db " /out: win32sam.exe"
db " /defaultlib:kernel32.lib"
db " /defaultlib:user32.lib"
db " /export:SayHello"
db " /entry:main"
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 [__imp__MessageBoxA@16]
ret 16
_main:
call SayHello
push 0
call _ExitProcess@4
使用link.exe与kernel32.lib、user32.lib链接命令如下:
cmd> nasm -fwin32 win32sam.asm
cmd> link win32sam.obj
2、使用golink。例子如下:
;filename: win32sam.asm
extern __imp__MessageBoxA@16 ;in user32.dll 或是__imp_MessageBoxA@16
extern _ExitProcess@4 ;in kernel32.dll
global SayHello
global _main
[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 [__imp__MessageBoxA@16] ; 或是__imp_MessageBoxA@16
ret 16
_main:
call SayHello
push 0
call _ExitProcess@4
使用链接命令如下:
cmd> nasm -fwin32 -o win32sam.obj win32sam.asm
cmd> GoLink.exe /entry _main win32sam.obj kernel32.dll user32.dll
3、使用alink.exe与win32.lib。例子如下:
;filename: win32sam.asm
extern __imp_MessageBoxA ;in user32.dll
extern ExitProcess ;in kernel32.dll
global SayHello
global _main
[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 [__imp_MessageBoxA]
ret 16
_main:
call SayHello
push 0
call ExitProcess
链接命令如下:
cmd> nasm -fwin32 win32sam.asm
cmd> alink -oPE -entry _main win32sam.obj win32.lib
三、标准coff文件格式链接:这种文件格式不支持info字段,不支持align对齐:
1、使用微软link.exe与kernel32.lib、user32.lib。例子如下:
;filename: win32sam.asm
extern __imp__MessageBoxA@16 ;in user32.dll
extern _ExitProcess@4 ;in kernel32.dll
global SayHello
global _main
[SECTION .text USE32]
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 [__imp__MessageBoxA@16]
ret 16
_main:
call SayHello
push 0
call _ExitProcess@4
链接命令如下:
cmd>nasm -f coff -o win32sam.obj win32sam.asm
cmd>link /subsystem:windows /defaultlib:kernel32.lib /defaultlib:user32.lib /export:SayHello /entry:main win32sam.obj
2、使用golink。例子如下:
;filename: win32sam.asm
extern __imp__MessageBoxA@16 ;in user32.dll 或是__imp_MessageBoxA@16
extern __imp__ExitProcess@4 ;in kernel32.dll 或是__imp__ExitProcess@4
global SayHello
global _main
[SECTION .text USE32 ]
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 [__imp__MessageBoxA@16] ;或是__imp_MessageBoxA@16
ret 16
_main:
call SayHello
push 0
call [__imp__ExitProcess@4] ;或是__imp_MessageBoxA@16
使用链接命令如下:
cmd> nasm -fcoff -o win32sam.obj win32sam.asm
cmd> GoLink.exe /entry _main win32sam.obj kernel32.dll user32.dll
========================================================
3、使用alink.exe与win32.lib。例子如下:
;filename: win32sam.asm
extern __imp_MessageBoxA ;in user32.dll
extern __imp_ExitProcess ;in kernel32.dll
global SayHello
global _main
[SECTION .text USE32]
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 [__imp_MessageBoxA]
ret 16
_main:
call SayHello
push 0
call [__imp_ExitProcess]
链接命令如下:
cmd> nasm -fcoff -o win32sam.obj win32sam.asm ?
cmd> alink -oPE -entry _main win32sam.obj win32.lib