NASM网际编译器手册(六)

NASM,虽然避免象MASM和TASM的官方编译器但也被迫支持一些宏。下面将描述这些内容。
NASM的定向符有两种类型:用户级的用户定向符和原始级的原始定向符。典型的说,每一个定向符都有一个用户级的和原始级的。在通常情部优下,我们推荐用户使用用户级的,而宏调用原始级的。
原始级的定向符将用方括号包含;用户级的则无所谓。
在这章描述的定向符中,每个目标文件格式都能可选的支持外部的定向符,为的是在文件格式中控制得的更
容易些。这些指定格式的格式定向符将在第六章描述。


5.1 BITS:指定目标处理模式
BITS定向符指定了NASM生成的代码是16位处理模式还是32位处理模式的。这个语法分别是BITS16或BIT32。
在最许多情况下,你不必明确的用BITS。被设计用在32位系统中的aout,coff,elf和win32目标格式,会使NASM来
选择32位的默认模式。obj目标格式允许你为每一个段指定USE16或USE32,NASM将根据它的操作模式为设置。
所以人用BITS定向符将不再需要。
用BITS定向符的主要原因是在一个平坦模式的二进制文件中写一个32位;这是由于二进制的输出格式默认为16
位模式来为写成DOS和COM的程序准备,DOS的.SYS设备驱动程序 和系统引导程序。
你在一个16位的DOS程序为了用32位指令而用BITS32为指定生成模式。如果你这样做编译器将会由于生成了
一个在16位机器上运行32位代码而生成错误的代码。
当NASM在BITS16下的状态时,用32位的数据用0x66加前缀,而用0x67前缀则表示一个32位的地址。在32位的
状态时,正好是相反:32位指令不需要前缀,16位数据需要0x66而16位地址则需要0x67。
BITS有一个等价的原始格式,[BITS 16]和[BITS 32]。用户级格式是一个不能调用原始格式的宏。


5.2 SECTION或SEGMENT:改变和定义段
SECTION定向符(SEGMENT是一个等价形式)来改变输出文件的段。在一些目标文件格式,一个数的数量和名
字是可以修改;可以按照用户的需要来构造宏。如果你想切换到一个来存在段,SECTION将会给出一条错误信息
或定义一个新段。
Unix目标格式或二进制目标格式,为代码,数据和非初始化数据段提供.text,.data和.bss段名字。相对来说,目标
格式不能识别指定的目标段名字并会去掉段名字的引导阶段。


5.2.1 _SECT_宏
SECTION定向符与它的原始格式的区别为不常用在用户级的格式。原始格式[SECTION xyz],可以简单的将目标段
切换到一个给定的段。用户格式SECTION xyz,首先定义了一个单行宏_SECT_来成为一个原始宏[SECTION]定向
能执行的方式 ,所以用户定向符:
SECTION .text
将扩展成
%define _SECT_[SECTION.text]
[SECTION.text]
用户可以发现用它们自己的宏来使用可能很有用。例如,在第4.2.3节中定义的writefile宏将会用下面复杂的格式
重写:
%macro writefile 2+
[section.data]
%%str: db %2
%%endstr:
_SECT_
mov dx,%%str
mov cx,%%endstr-%%str
mov bx,%1
mov ah,0x40
int 0x21
%endmacro
上面的宏格式交一个字符串传到输出文件,首先将临时切换到文件的数据,用SECTION的原始格式不能修改
_SECT_。它将在数据段定义字串,然后执行_SECT_切换回先前执行的段。在前一个版本的宏中避免跳过数据段
为了包含一个JMP指令,在某些方面个复杂的OBJ格式模块中用户可以在不同的代码段中进行汇编。


5.3 ABSOLUTE:定义绝对标号
ABSOLUTE定向符是SECTION的一个变化格式:它对一个不直接在物理段的子代码在给定的绝对地址开始。你只
能在RESB相关指令中使用。ABSOUTE用法如下:
absolute 0x1a
kbuf_chr resw 1
kbuf_free resw 1
kbuf resw 16
这个例子描述了一个PC BIOS数据区的段,在段地址为0x40:定义了kbuf_chr为0x1a,kbuf_free为0x1c和kbuf为0x1e。
ABSOLUTE的用户级格式象SECTION一样,在它被执行时被定义为_SECT_。
STRUC和ENDSTRUC可以用ABSOLUE(也可以用_SEC_)宏定义。ABSOLUTE不一定带一个绝对的参数:它可以
带一个表达式(一个临界表达式:见第3.7节)也可以是一个段中的值。例如:一个TSR象运行时的BSS一样重
用它的setup代码:
org 100h ;它是一个.COM程序
jmp setup ;跳到后的设置代码
;TSR中的驻留部分
setup: ;现在写一个安装TSR的代码
absolute setup
runtimevar1 resw 1
runtimevar2 resd 20
tsr_end:
在安装代码上定义了一些变量,所以在安装运行完后,它将为运行TSR存储空间来重新放数据。符号\'tsr_end\'
用来计算TSR的驻留部分的总尺寸。


5.4 EXTERN:从其它模块中引入符号
EXTERN与MASM的定向符EXTRN和C语言的关键字extern相似:它被用来引用一个不在模块中定义的符号,但
在其它模块中定义 了它并且被这个模块引用。不是每一种文件格式都支持引用的变量:bin格式就不支持。
EXTERN定向符可以带很多参数,每一个参数是一个符号的名字:
extern _printf
extern _sscanf,_fscanf
有一些目标文件格式提供了EXTERN定向符的外部特性。在所有情况下,外部特性用一个后缀的冒号跟在目标
文件指定文件的符号名。例如目标格式允许你来定义一个默认段的外部基位置 为一个定向符dgroup
extern _variable:wrt dgroup
EXTERN的原始格式与它的用户格式的区分为一次只能带一个参数:多个参数的支持在预处理器级上执行。
你可以用EXTERN多次定义相同的变量 :NASM将会忽略第二个及后面的重定义。你不能用EXTERN定义象
EXTERN的变量 。


5.5 GLOBAL:导出符号到其它模块
GLOBAL是EXTERN的结束标志:如果一个模块用EXTERN定义了一个符号并引用它,为了避免连接器的错误,其
它的模块必须定义这个标号并用GLOBAL来定义。一些编译器用PUBLIC来支持这个操作。
GLOBAL定向符必须在符的定义前出现。
GLOBAL的用法与EXTERN的用法相同,但它必须用在与GLOBAL定向符相同的模块中,例如:
global _main
_main: ;一些代码
GLOBAL,象EXTERN一样允许目标格式定义一个自己的扩展用一个冒号区分,elf目标格式例如 ,可以允许你
指定全局数据项是functions或data
global hashlookup:function,hashtable:data
象EXTERN一样,GLOBAL原始格式与用户级区别为它一次只用一个参数。


5.6 COMMON:定义常用数据区
COMMON定向符用来定义一个常用的变量,常用变量可以是一个非初始化数据段的全局变量,如下
common intvar 4
与下面功能相似
global intvar
section .bss
intvar resd 1
不同的是如果多个模块定义了相同的变量,那么在连接时这些变量将合并,在所有模块对这人变量的引用 会
在内丰中一个指定的位置。

象GLOBAL和EXTERN,COMMON支持目标格式指定的扩展,例如obj格式允许常用变量为NEAR或FAR而elf格式
则允许你指定一个常用变量的对齐格式:
common commvar 4:near ;在OBJ文件中
ommon intarray 100:4 ;在ELF中:4个字节对齐
象EXTERN和GLOBAL一样,COMMON的原始格式与用户级格式的区别为它一次只能带一个参数。

posted on 2009-01-06 16:46  cnlmjer  阅读(243)  评论(0编辑  收藏  举报