伪指令(pseudo-instructions)是指那些并不是x86机器指令但是需要写在代码中的instruction位置的东西。目前支持伪指令有数据初始化指令DB, DW, DD, DQ,DT, DO, DY 和 DZ;数据不初始化指令 RESB,RESW,RESD, RESQ, REST, RESO,RESY 和 RESZ;INCBIN命令;EQU命令;TIMES前缀。
DB, DW, DD, DQ,DT, DO, DY 和 DZ的使用方式与其在MASM中的使用方式一致,用于在输出文件中声明初始化后的数据。有多种调用他们的方式:
db 0x55 ;声明一个值为0x55的byte
db 0x55,0x56,0x57 ; 连续声明三个byte
db 'a',0x55 ; 使用字符常数也是可以的
db 'hello',13,10,'$' ; 使用字符串常量也是可以的
dw 0x1234 ; 0x34 0x12
dw 'a' ; 0x61 0x00
dw 'ab' ; 0x61 0x62
dw 'abc' ; 0x61 0x62 0x63 0x00
dd 0x12345678 ; 0x78 0x56 0x34 0x12
dd 1.234567e20 ; 单精度浮点数常量
dq 0x123456789abcdef0 ; 八字节常量
dq 1.234567e20 ; 双精度浮点数
dt 1.234567e20 ;扩展精度浮点数
DT, DO, DY 和 DZ 不接受数字常数作为操作数。
RESB, RESW, RESD,RESQ, REST, RESO, RESY 和 RESZ 被用在模块的BSS段中。它们声明一块存储空间,而这块存储空间不会被初始化。使用时需要指定一个操作,这个操作数是预保留的存储空间大小,单位分别为byte,word,doubleword等。正如在2.2.7节所述,NASM不支持 MASM或TASM声明不初始化数据的语法,如:DW ?
。
The operand to a RESB–type pseudo-instruction is acritical expression: see section 3.8. 暂时不知道什么意思。
buffer: resb 64 ; 预留64个byte
wordvar: resw 1 ; 预留1个word
realarray resq 10 ; 长度为10的实数数组
ymmval: resy 1 ; 一个YMM寄存器
zmmvals: resz 32 ; 32个ZMM寄存器
INCBIN
是借鉴了古老的Amiga汇编器:使用它可以在输出文件中直接进入外部二进制文件的内容。如,可以将图像或声音数据直接插入游戏的可执行文件中。有以下三种调用方式:
incbin "file.dat" ; 引入整个文件
incbin "file.dat",1024 ; 跳过开始的1024个字节
incbin "file.dat",1024,512 ; 跳过开始的1024个字节,最多引入512个字节。
INCBIN
既是指令又是标准宏;标准宏版本在文件搜索目录中搜索文件,并将文件加入到依赖列表中。如果需要,可以覆盖此宏。
EQU
用于给常量定义一个符号。使用EQU
时,代码行中必须包含label。EQU会将label名称定义成给定的操作数的值,EQU只有一个操作数。定义是绝对的,并且不能被修改的,如:
message db 'hello, world'
msglen equ $-message
msglen
被定义成12。msglen
之后不能再被重新定义。这也不是预处理定义,因为msglen
和$
的值是只通过一次计算获得的,而不是在每次引用它们的地方都计算一次。关于$
的说明参见3.5节。
TIMES
会使指令被汇编多次。使用TIMS
部分原因是NASM不支持MASM的DUP
语法,你可以使用类似以下方式代替MASM的DUP
语法。
zerobuf: times 64 db 0
TIMES
的作用不仅如此。TIMES
的操作数不仅可以是常数,还可以是表达式。
buffer: db 'hello, world'
times 64-$+buffer db ' '
以上代码可以将buffer预留的空间扩展到64btye,并且在hello,world
之后的填充空格。最后TIMES
可以用来允许地重复指令,因此可以使用它简化某些循环操作:
times 100 movsb
注意times 100 resb 1
和resb 100
在最终效果上没有区别,但在汇编阶段NASM处理后者会更快一些。
The operand to TIMES is a critical expression(section 3.8). 不知道什么意思。暂不翻译
另外注意TIMES不能用于宏。原因在于TIMS的处理在宏处理之后。如果只是想单纯重复代码行,或者重复一个复杂的宏,可以使用预处理指令-%rep