在function文件里写这个:
global _func
在main文件里写这个
extern _func
然后编译时都先用nasm编译成obj,然后用ld链接到一块。
nasm如果不提供输出文件格式,默认的输出文件格式是 bin
NASM 在缺省状态下是一个两遍的汇编器。
mov ax,es:[di]是错误的,mov ax,[es:di]是正确的。mov word [var],2是正确的。mov eax,[ebx*2+ecx+offset]正确
NASM 使用跟 MASM 不同的浮点寄存器名:MASM 叫它们'ST(0)','ST(1)'等,而'a86'叫它们'0','1'等,NASM 则叫它们'st0','st1'等。
'tag resb 64',读作"保留 64 字节" 声明未初始化的数据。
NASM 使用反斜线(\)作为续行符;如果一个以一个反斜线结束,那第二行会被认为是前面一行的一部分。多用于字符串吧。
labels 中的有效的字符是字母,数字,'-','$','#','@','~','.'和'?'。但只有字母'.',(具有特殊含义,参阅 3.9),'_'和'?'可以作为标识符的开头。一个标识符还可以加上一个'$'前缀,以表明它被作为一个标识符而不是保留字来处理。这样的话,如果你想到链接进来的其他模块中定义了一个符号叫'eax',你可以用'$eax'在NASM 代码中引用它,以和寄存器的符号区分开。
`INCBIN':包含其他二进制文件。
'INCBIN'是从老的 Amiga 汇编器 DevPac 中借过来的:它将一个二进制文件逐字逐句地
包含到输出文件中。这能很方便地在一个游戏可执行文件中包含中图像或声音数
据。它可以以下三种形式的任何一种使用:
incbin "file.dat" ; include the whole file
incbin "file.dat",1024 ; skip the first 1024 bytes
incbin "file.dat",1024,512 ; skip the first 1024, and
; actually include at most 512
message db 'hello, world'
msglen equ $-message
buffer: db 'hello, world'
yes: times 64-$+buffer db ' '
'jmp $'来表示无限循环。
'$$'计算当前段开始处的地址,所以你可以通过($-$$)找出你当前在段内的偏移。
相当实用
'/'是无符号除,'//'是带符号除。同样的,'%'和'%%'提供无符号与带符号的模运算。
第一遍汇编是用于确定所有的代码与数据的尺寸大小,这样的话,在第二遍产生代码的时候,就可以知道代码引用的所有符号地址。所以,有一件事NASM 不能处理,那就是一段代码的尺寸依赖于另一个符号值,而这个符号又在这段代码的后面被声明。比如:
times (label-$) db 0
label: db 'Where am I?'
在前面可以,后面不行。
'EXTERN'操作符可以带有任意多个参数,每一个都是一个符号名:extern _sscanf,_fscanf
'GLOBAL'使用跟'EXTERN'相同的语法,除了它所引用的符号必须在同一样模块中已经被
定义过了,比如:
global _main
C 编译器对所有的全局符号(函数或数据)的名字有一个转化,它们被定义为在名字前面加上一个下划线,就象在 C 程序中出现的那样。所以,比如,一个 C 程序的函数'printf'对汇编语言程序中来说,应该是'_printf'。你意味着在你的汇编程序中,你可以定义前面不带下划线的符号,而不必担心跟 C 中的符号名产生冲突,但是asm文件本身不用吧
对于汇编链接,必须使用C语言的东西,如果上C语言,那么就可以链接了,因为只要我写的转义成nasm代码就可以了。
联立两个纯bin文件是不行的。
使用’bin'格式来产生`.EXE'文件。
'.EXE'文件是相当简单的,所以可以通过编写一个纯二进制文件然后在前面
连接上一个 32bytes 的头就可以产生一个'.exe'的文件了。这个文件头也是
相当简单,它可以通过使用 NASM 自己的'DB'和'DW'命令来产生,所以你可以使
用'bin'输出格式直接产生'.EXE'文件。
在 NASM 的包中,有一个'misc'子目录,这是一个宏文件'exebin.mac'。它定义
了三个宏`EXE_begin',`EXE_stack'和`EXE_end'.
要通过这种方法产生一个'.EXE'文件,你应当开始的时候先使用'%include'载
入'exebin.mac'宏包到你的源文件中。然后,你应当使用'EXE_begin'宏(不带
任何参数)来产生文件头数据。然后像平常一样写二进制格式的代码-你可以
使用三种标准的段'.text','.data','.bss'.在文件的最后,你应当调用
'EXE_end'宏(还是不带任何参数),它定义了一些标识段 size 的符号,而这些宏
会由'EXE_begin'产生的文件头代码引用。
在这个模块中,你最后的代码是写在'0x100'开始的地址处的,就像是'.COM'文
件-实际上,如果你剥去那个 32bytes 的文件头,你就会得到一个有效的'.COM'程
序。所有的段基址是相同的,所以程序的大小被限制在 64K 的范围内,这还是跟
一个'.COM'文件相同。'ORG'操作符是被'EXE_begin'宏使用的,所以你不必自己
显式的使用它
你可以直接使用你的段基址,但不幸的是,因为这需要在文件头中有一个重定
位,事情就会变得更复杂。所以你应当从'CS'中拷贝出一个段基址。
进入你的'.EXE'文件后,'SS:SP'已经被正确的指向一个 2Kb 的栈顶。你可以通过
调用'EXE_stack'宏来调整缺省的 2KB 的栈大小。比如,把你的栈 size 改变到
64bytes,你可以调用'EXE_stack 64'
一个关于以这种方式产生一个'.EXE'文件的例子在 NASM 包的子目录'test'中,
名字是'binexe.asm'