202X年我的汇编学习之路(1):指令

上传人:tang****xu1 文档编号:147016613 上传时间:2020-10-05 格式:DOCX 页数:3 大小:34.70KB
返回 下载 相关 举报
202X年我的汇编学习之路(1):指令_第1页
第1页 / 共3页
202X年我的汇编学习之路(1):指令_第2页
第2页 / 共3页
202X年我的汇编学习之路(1):指令_第3页
第3页 / 共3页
亲,该文档总共3页,全部预览完了,如果喜欢就下载吧!
资源描述

《202X年我的汇编学习之路(1):指令》由会员分享,可在线阅读,更多相关《202X年我的汇编学习之路(1):指令(3页珍藏版)》请在金锄头文库上搜索。

1、引言我们很多人是开发者,每天写大量的代码,有时也不是糟糕的代码。每个人都能很轻松 写下这样的代码:#include <stdio.h>int main() (int x = 10;int y = 100;printf(x + y = %d, x + y);return 0;大家都能理解上面这段C语言代码完成的功能,但是这段代码底层是如何工作的呢?我想我们中间不是所有人都能回答这个问题,我也不能。我认为我可以用高级编程语言写代码,例如 Haskell、Erlang、Go等等,但是我完全不知道在编译之后它在底层是如何工 作的。所以,我决定往下再深入一步,到汇编这个层次,并且记录下我的学

2、习汇编之路。希 望这是有趣的过程,而不是仅仅对我一个人。大约五、六年前我已经使用过汇编来写简单的 程序,那时我还在上大学,用的是Turbo汇编和 DOS操作系统。现在我使用 Linux-x86_64 操作系统,是的,64位Linux和16位DOS肯定有很大的不同。那我们就开始吧。准备阶段在开始之前,我们需要准备一些我接下来要提到的东西。我使用的是Ubuntu(Ubuntu14.04.1 LTS 64位)系统,因此我的文章都是基于该操作系统和体系结构的。不同的CPU支持不同的指令集,我使用的是Intel Core i7 870处理器,所有代码都在这上面运行。另外我将用nasm汇编,你可以用下面命

3、令来安装:sudo apt-get install nasmI它的版本应该是 2.0.0或者更高了。我是用的是2013年12月29日编译的 NASMversion 2.10.09版本。最后一部分,你需要一款写汇编代码的文本编辑器,我使用配有 nasm-mode.el的Emacs编辑器。当然这不是强制性的,你可以选择任何你喜欢的文本编辑 器。如果你像我一样使用的是Emacs,你可以下载 nasm-mode.el,将你的Emacs配置成这样:(load /.emacs.d/lisp/nasm.el)(require nasm-mode)(add-to-list auto-mode-alist (.

4、(asm|s)$ . nasm-mode)这就是目前我们需要准备的所有东西,其它工作在接下来的文章中会提到。x64语法这里我就不全面介绍汇编的语法了,我们仅提一下这篇文章中用到的语法。通常NASM程序会被划分为不同的段(section),这篇文章中我们会涉及到两个段:数据段(data section)代码段(text section)数据段用来定义常量(constant),常量是在运行时不会改变的数据。你可以定义数字或 其他常量等等,声明一个数据段的语法如下:section .data代码段是存放代码(code)的,该段必须以global_start开始,告诉内核这里是程序开始执行的地方。se

5、ction .text global _start start:注释是以;开始。每个 NASM 代码行包含下面四个字段的组合:label: instruction operands ; comment中括号括起来的字段表示是可选的。基本NASM指令由两部分组成,第一部分是需要执行指令的名字,第二部分是该指令的操作数。例如:MOV COUNT, 48 ;将数值48存放到 COUNT变量中Hello world让我们用NASM汇编来写第一个程序吧,当然是传统的打印“Hello world”的程序。这是代码:section .datamsg db hello, world!section .text

6、global _startstart:mov rax, 1mov rdi, 1mov rsi, msgmov rdx, 13syscallmov rax, 60mov rdi, 0syscall值为 Hello world ,那么我们以及程序的入口,代码从第mov指令的功能,它带rax、rdi等等这些是什么的,看起来不像 printf( Hello world ),我们试着去理解它是什么、怎么工作的。先 看1-2行,我们定义了一个数据段,并且有一个 msg常量, 就可以在代码中使用这个常量了。下一步是定义了一个代码段,7行开始执行。现在到了程序最有意思的部分了。我们已经了解了 有两个操作数,将

7、第二个操作数的值放到第一个操作数中。但是, 呢?我们找到维基百科的解释:中央处理单元(CPU)是计算机中的硬件,它读取计算机程序中的指令,完成系统中基 本的算术、逻辑、输入/输出操作。它涉及到复杂的CPU有其内部的存储位置,称为寄存器好了,CPU完成一些操作,例如算术操作等,但是它从哪获得操作的数据呢?第一个 答案是内存。然而从内存中读取和存入数据的速度远远低于处理器的速度, 通过控制总线来发送数据请求的过程。因此, (register)。x64_registersrax寄存器中。现在我们知道什么是rax,什么时候使用rsi等等。rax保存系统调用号rax、那么我们写 mov rax, 1 ,

8、意思是将1放到 rdi、rbx等等了吧,但是还需要知道什么时候使用rax 临时寄存器,当我们调用系统调用时,rdx 用来向函数传递第三个参数rdi 用来向函数传递第一个参数rsi用来向函数传递第二个参数的指针换句话说,我们就是调用了sys_write系统调用,该函数原型是:ssize_t sys_write(unsigned int fd, const char *buf, size_t count)它有三个参数: fd文件描述符,0、1、2分别代表标准输入、标准输出和标准错误buf字符数组的指针,用来保存从fd指向的文件中获取的内容count表示要从文件中读入到字符数组的字节数我们知道sys

9、_write系统调用带有三个参数,它在系统调用表中有一个系统调用号。我们再看看程序的实现,将 1放到rax寄存器中,它意思是我们使用sys_write系统调用;下一行将1存到rdi寄存器,它是 sys_write的第一个参数,1代表标准输出;然后我们 将msg的指针存到rsi寄存器中,这是 sys_write的第二个参数buf;接着我们传递sys_write最后一个参数(字符串的长度)至Vrdx寄存器中。现在,我们有了 sys_write的所有参数,就可以在11行使用syscall来调用它了。好了,我们打印出Hello world 字符串,现在需要从程序中正确退出。我们传递 60到rax寄存器

10、,60是exit的系统调用 号;以及将 0传递给rdi寄存器,这是错误码,0表示我们的程序正确地退出。这就是“Hello world ”的所有分析,相当简单吧:)现在我们编译程序,假设我们的程序放在hello.asm文件中,那么我们需要运行下面的命令来执行:nasm -f elf64 -o hello.o hello.asmld -o hello hello.o编译链接完成之后,我们得到可执行文件hello,可以使用./hell。来运行,可以在终端看到输出Hello world 。总结本文用一个简单不能再简单的程序开始第一部分,接下来我们会看到一些算术运算。如果你有任何问题或者建议可以给我评论。更多信息请查看IT技术专栏

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 办公文档 > 其它办公文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号