什么是汇编语言大部分人都应该是知道的,但是,实际上在很多公司开发上都没有用到汇编语言,那么,这汇编有什么用呢?
比如说逆向工程,这是玩逆向的基础,看不懂汇编玩不起。
汇编的基本语法
汇编语言通常分为两部分
- data section
text section
data section 通常用来声明常量,所谓常量,就是在运行时候不被程序
所改变的变量,语法为
section .data
text section是代码段,这里必须要以global _start开始以便系统能够知道从哪里开始执行程序,语法为
section .text
global _start
_start:
汇编中的注释用 “;”
会变得代码中,每一行都是由于以下部分构成
[label:] instruction [operands] [; comment]
eg:MOV COUNT, 48 ; Put value 48 in the COUNT variable
汇编版的Hello,world
section .data
msg db "Hello,world!"
section .text
global _start
_start:
mov rax, 1
mov rdi, 1
mov rsi, msg
mov rdx, 13
syscall
mov rax, 60
mov rdi, 0
syscall
这就是汇编版的一个hello,world了,我们来理解以下它是怎工作的。
首先,我们在data section定义了常量”Hello,world!” ,这样,在我们的代码中就可以使用这个常量了。下一步是定义text section和程序的入口,这样程序就会从_start开始执行了。接下来是关键部分了。mov操作大家想必知道是干什么用的了,mov指令有两个操作数,mov会吧第二个操作数存放在第一个操作数里。但是,rax、rdi、rsi是什么?维基百科这样解释的:
A central processing unit (CPU) is the hardware within a computer that carries out the instructions of a computer program by performing the basic arithmetical, logical, and input/output operations of the system.
CPU可以执行某些算术算法、操作。。。但CPU的这些操作从哪里获取这些数据呢?
内存?!CPU从内存读写数据的速度远远慢与CPU的运行速度,所以CPU内部的存储器–寄存器(registers)
mov rax, 1,就是把1存储到rax寄存器里。我们知道rax,rdi,rbx是什么了,也需要知道什么时候用它:
- rax 当我们调用一个系统调用(syscal),rax必须是系统调用好(syscall number)
- rdx 用来传递函数的第三个参数
- rdi 用来传递函数的第二个参数
- rsi 第二个函数参数的指针
在我们的hello,world程序中,我们调用了系统调用 sys_write,sys_write的声明:
size_t sys_write(unsigned int fd, const char * buf, size_t count);
他有三个参数:
- fd 文件描述符,可以是0,1,2对应标准输入、标准输出、标准错误流
- buf 指向字符数组的指针,这个字符数组可以用来保存写到文件描述符的内容
- count 写入文件描述符的字符数量
sys_write接收三个参数,并且在syscall table中的序号是1。在我们的hello,world程序中,mov rax, 1,表示我们要调用系统调用函数sys_write,在下一行中,mov rdi,1。1将是sys_write函数的第一个参数,1-标准输出。随后,我们把要输出的消息存放到rsi中,它是sys_write的第二个参数。最后rdx是sys_write的第三个参数,即所要输出的字符串的长度。sys_write的三个参数都有了,最后我们调用syscall来调用sys_write函数。在程序执行后,我们可以看到屏幕上会输出hello,world字符串。程序执行完之后,我们需要退出程序,在这里,用了mov rax, 60。60是exit函数的syscall number.并且,执行mov rdi, 0。他是我们程序的错误码,0表示我们的程序执行成功,正常退出。
程序在ubuntu17.0中用nasm编译,nasm的安装命令如下:
sudo apt-get install nasm
之后,我们可以调用:
$ nasm -f elf64 -o hello.o hello.asm
$ ld -o hello hello.o
这样就完成了汇编语言的编译了,直接./hello就可以看到界面上输出了hello,world。
附上原版的英文文章:https://0xax.github.io/asm_1/