| title | 译文: Say hello to x64 Assembly [part 5] | ||
|---|---|---|---|
| date | 2016-08-15 08:51:19 -0700 | ||
| categories | style | ||
| tags |
|
Say hello to x86_64 Assembly 系列的第五篇,这篇会看到宏(macros)。但这与 x86_64 并没有关系,仅仅是 nasm 这种汇编工具与其预处理的。若有兴趣的话可以接着阅读。
NASM 支持以下两种形式的宏:
- 单行(single-line)
- 多行(multiline)
所有单行定义的宏必须以%define开始,像下面的形式一样:
%define macro_name(parameter) valueNasm 宏的行为与 C 非常相似。比如,我们可以这样创建单行宏:
%define argc rsp + 8
%define cliArg1 rsp + 24之后可以在代码中这么使用他们:
;;
;; argc 将会被 扩展为 rsp + 8 (argc will be expanded rsp + 8)
;;
mov rax, [argc]
cmp rax, 3
jne .mustBe3args多行宏以%macro起始,以%endmacro结束。通常的形式是这样的:
%macro number_of_parameters
instruction
instruction
instruction
%endmacro例如(译者注:1 代表参数的个数为 1):
%macro bootstrap 1
push ebp
mov ebp, esp
%endmacro然后这样使用它:
_start:
bootstrap再举几个 PRINT 宏的例子:
%macro PRINT 1
pusha
pushf
jmp %%astr
%%str db %1, 0
%%strln equ $-%%str
%%astr: _syscall_write %%str, %%strln
popf
popa
%endmacro
%macro _sytcall_write 2
mov rax, 1
mov rdi, 1
mov rsi, %%str
mov rdx, %%strln
syscall
%endmacro让我们浏览一遍、懂得他们是怎样工作的:第一行定义了 PRINT 宏,参数为 1。之后利用 pusha 与 pushf 指令把所有数据与标志(flag, pushf 指令)入栈。然后跳向 %%astr 标签继续执行。注意到宏定义的所有的标签都以 %% 开始。现在转向 _syscall_write 宏,它的参数为 2。_syscall_write 是怎么执行的呢?是否还记得我们使用的 write 系统调用来打印字符至标准输出。它长成这样:
;; write syscall number
mov rax, 1
;; file descriptor, standard output
mov rdi, 1
;; message address
mov rsi, msg
;; length of message
mov rdx, 14
;; call write syscall
syscall在我们的 _syscall_write 宏中,我们先使用两条指令把 1 放入 rax(write system call number)与 rdi(stdout file descriptor)。之后把 %%str 放入 rsi 寄存器(指向字符串),%%str 是局部标签,它获取 PRINT 宏的参数(要注意宏的参数可以使用 $parameter_number),%%str 以 0 结束(每个字符串必须以 0 结束)。%%strln 为计算出的字符串的长度。最后进行了系统调用。
现在便可以这样使用它:
label: PRINT "Hello World!"NASM 支持下列形式的标准宏:
STRUC
可以为数据指令(data structure)使用STRUC与ENDSTRUC。例如:
struc person
name: resb 10
age: resb 1
endstruc现在可以这样为上面的指令创建一个实例:
section .data
p: istruc person
at name db "name"
at age db 25
iend
section .text
_start:
mov rax, [p + person.name]%include
可以 include 其他的汇编文件,然后跳转到这些文件中的某一行继续执行,或者调用其中的函数。
...
译者罗嗦几句:感觉这结语没啥好翻译的,与前面都差不多;也并没学会宏,使用的话看还是再找些资料读吧。