首页
社区
课程
招聘
[翻译]Say hello to x86_64 Assembly [part 5]
2020-1-14 11:00 9150

[翻译]Say hello to x86_64 Assembly [part 5]

2020-1-14 11:00
9150

Say hello to x86_64 Assembly [part 5]

最近在学习x64汇编,在github上面找到了一点学习资料,入门级别的,因为想细致的学习一下,所以顺便久把作者的内容都翻译了一下,也不知道自己翻译的是否合适,请大家看看有问题的地方请批评指正.第一次做翻译,做的不好请大家原谅,

 

作者原文


 

这是Say hello to x86_64 Assembly的第五部分,下面我们将介绍宏。它不会是关于x86_64的博客文章,主要是关于nasm汇编程序及其预处理器的。如果你对它感兴趣,请看下一篇。

 

It is a fifth part of Say hello to x86_64 Assembly and here we will look at macros. It will not be blog post about x86_64, mainly it will be about nasm assembler and it’s preprocessor. If you’re interesting in it read next.

Macros

 

NASM支持两种形式的宏:
-单行
-多行
所有单行宏都必须从%define指令开始。其形式如下:

 

NASM supports two form of macro:

  • single-line
  • multiline

All single-line macro must start from %define directive. It form is following:

%define macro_name(parameter) value

Nasm宏的行为和外观与C中的非常相似。例如,我们可以创建以下单行宏:

 

Nasm macro behaves and looks very similar as in C. For example, we can create following single-line macro:

%define argc rsp + 8
%define cliArg1 rsp + 24

在代码中使用它:

 

and than use it in code:

;;
;; argc will be expanded to rsp + 8
;;
mov rax, [argc]
cmp rax, 3
jne .mustBe3args

多行宏以%macro nasm指令开头,以%endmacro结尾。一般形式如下:

 

Multiline macro starts with %macro nasm directive and end with %endmacro. It general form is following:

%macro number_of_parameters
    instruction
    instruction
    instruction
%endmacro

例如:

 

For example:

%macro bootstrap 1
          push ebp
          mov ebp,esp
%endmacro

我们可以使用它:

 

And we can use it:

_start:
    bootstrap

例如,让我们看看PRINT宏:

 

For example let’s look at PRINT macro:

%macro PRINT 1
    pusha
    pushf
    jmp %%astr
%%str db %1, 0
%%strln equ $-%%str
%%astr: _syscall_write %%str, %%strln
popf
popa
%endmacro

%macro _syscall_write 2
    mov rax, 1
        mov rdi, 1
        mov rsi, %%str
        mov rdx, %%strln
        syscall
%endmacro

让我们试着浏览一下它的宏并了解它是如何工作的:在第一行,我们用一个参数定义了PRINT宏。然后推送所有通用寄存器(使用pusha指令)和标记寄存器(使用pushf指令)。在此之后,我们将跳转到%%astr label。请注意,宏中定义的所有标签必须以“%”开头。现在我们转到带2个参数的 __syscall_write宏。让我们看看系统调用写入实现。您可以记住,我们在以前的所有文章中都使用写入系统调用将字符串打印到stdout。看起来是这样的:

 

Let’s try to go through it macro and understand how it works: At first line we defined PRINT macro with one parameter. Than we push all general registers (with pusha instruction) and flag register with (with pushf instruction). After this we jump to %%astr label. Pay attention that all labels which defined in macro must start with %%. Now we move to syscall_write macro with 2 parameter. Let’s look on syscall_write implementation. You can remember that we use write system call in all previous posts for printing string to stdout. It looks like this:

;; 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(写系统调用号)和rdi(stdout文件描述符)。然后我们将%str放入rsi寄存器(指向字符串的指针),其中,%str是本地标签,它是PRINT宏的第一个参数(注意宏参数通过$parameter_number访问),以0结尾(每个字符串必须以0结尾)。以及计算字符串长度的%strlen。在此之后,我们使用syscall指令调用系统调用,仅此而已。

 

In our __syscall_write macro we define first two instruction for putting 1 to rax (write system call number) and rdi (stdout file descriptor). Than we put %%str to rsi register (pointer to string), where %%str is local label to which is get first parameter of PRINT macro (pay attention that macro parameter access by $parameter_number) and end with 0 (every string must end with zero). And %%strlen which calculates string length. After this we call system call with syscall instruction and that’s all.

 

Now we can use it:

label: PRINT "Hello World!"

有用的标准宏

Useful standard macros

 

NASM支持以下标准宏:

 

NASM supports following standard macros:

结构

struc

 

我们可以使用'STRUC'和'ENDSTRUC'来定义数据结构。例如:

 

We can use STRUC and ENDSTRUC for data structure defintion. For example:

struc person
   name: resb 10
   age:  resb 1
endstruc

现在我们可以举例说明我们的结构:

 

And now we can make instance of our structure:

section .data
    p: istruc person
      at name db "name"
      at age  db 25
    iend

section .text
_start:
    mov rax, [p + person.name]

%include

我们可以包含其他程序集文件并跳转到其中的标签或使用%include指令调用函数。

 

We can include other assembly files and jump to there labels or call functions with %include directive.


[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界

收藏
点赞1
打赏
分享
最新回复 (2)
雪    币: 641
活跃值: (399)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
sunzhanwei 2020-1-14 11:03
2
0
感谢大家帮助,我终于能发帖了.赶紧发上来.谢谢
雪    币: 997
活跃值: (1518)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
WMBa0 2023-1-28 17:13
3
0
文章后面写的有点奇怪
游客
登录 | 注册 方可回帖
返回