本文转载自汇编语言基础:寄存器和系统调用
寄存器是处理器临时保存数据指令的的一部分。在x86_64
架构中,寄存器能处理高达64位的数据。这意味着每个寄存器都可以保存该值
没符号整数:0?18,446,744,073,709,551,616
有符号整数:-9,223,372,036,854,775,808 - 9,223,372,036,854,775,807
这是x86_64
架构下的所有寄存器的逻辑图表。
这是我们的寄存器列表,表中有有四列:
这里是rax
寄存器的图,你可以看到我们的一个64位寄存器叫做rax
,还有eax 32
位寄存器,那实际上不是它自己的寄存器,它是rax
寄存器的一半,那么ax
是16位寄存器是eax
寄存器的一半。同理al
寄存器是ax
寄存器的一半。使用al
寄存器就好像是一个8位寄存器,但它是 实际上修改了ax
寄存器的低8位。以上说的并不需要刻意记忆,因为本文的立足点是让你能够读懂别人或C/C++
编译器转译的汇编代码,你不记得的话,可以收藏本文已被你翻查。
不同数据长度的寄存器之间的关系
系统调用是指程序向系统内核请求服务,系统调用因操作系统的不同而不同,因为不同的操作系统使用不同的内核。
所有系统调用都有一个与之关联的ID(一个数字)
系统调用的输入接受一个参数列表。
寄存器参数顺序表
这是一个非常重要的表,当你使用系统调用时,它有许多输入是基于存储在寄存器中的值,并且是讲求顺序的,如果你想使用系统调用,你可以将对应系统调用的ID加载到rax
寄存器中 并按上表指定的顺序加载参数在你的RAX
寄存器中,如果你在这里还没有概念的话,可以跳过,往下看完一个示例,回头看就明白了。
rdi
寄存器,rsi
寄存器,rdx
寄存器r10
寄存器r8
寄存器r9
寄存器.我们这里只列出常用系统调用的ID,完整的系统调用ID列表,可以在网上都可以找得到。
系统调用ID示例表
Unix/Linux
交互的常用接口.ID列对应的数字和对应syscall
列对应系统调用名称相关联。前文写到Hello World
程序将"Hello World"字符串打印到屏幕,已经用到了sys_write
系统调用,我们作为示例来讲解一下寄存器和系统调用之间是如何交互的。
sys_write
参数类型
看完上面参数表,再回顾一下上面的寄存器ID参数表,看如何使用寄存器ID参数和下表的参数相关联,其实很简单,只需要将那些寄存器的值替换下表的参数列名即可。
所以,正如你所见
rax
寄存器应该处理值1(也即是sys_write
系统调用的ID),rdi
寄存器应该处理我们的文件描述符,rsi
寄存器应该处理字符串的缓存对象,rdx
寄存器应该处理字符串的长度.最后,按照《参数类型表》的描述替换为各列寄存器对应的值,具体分析逻辑如下,这样就生成我们最后关于Hello World程序关于系统调用的相关指令。
mov
:表示move
的意思就是移动数据,所以诸如如下语句
move rax,1
的意思就是将ID为1的sys_write
系统调用移动寄存器rax
,那么你应该记住,以后遇到类似move rax ID这样格式的命令就应该记住这是通过寄存器执行某项系统调用
。syscall
:每调用move
指令后以syscall
结尾,表示执行一次系统调用,也就是说你执行一个不同的系统调用都需要以syscall
关键字结束。mov rax 60
这条指令是关于系统调用ID等于60(从网上查到是sys_exit),关于告知操作系统,你的程序已经执行完毕,同理,move rdi 0是执行与描述符有关的操作,即告知程序退出的状态 ,事实上这个状态码你可以任意定义的,按照程序设计的一般约定,0代表程序执行正常退出,其他为异常状态
。section
:所有x86_64
的汇编文件有三种section
data
:该section下定义的所有变量,在汇编之前,编译器会完成所有相关变量指向对应内存位置的值的替换。你可以理解为C/C++的变量相关的操作。.bss
该section,为某些功能的使用而分配内存,和.data
section有些类似.text
该section,主要定义程序运行的逻辑和各种的系统调用。label
:标签用于标记代码的一部分。在编译时,编译将计算标签在内存中的位置。 每次使用标签的名称后,该名称将被编译器替换为内存中的位置。如果你看看helloword定义text的位置,它基本上是相同的,除了我们可以在位置插入这些标签。在我们的代码中将会看到为什么它在将来会有用武之地。
start
:标签对所有程序都至关重要。当您编写程序并稍后执行时,它首先在“_start”的位置执行。如果链接器找不到“_start”标签,则会抛出错误。global
:当您希望链接器能够知道某个标签的地址时,使用global关键字。 生成的目标文件将包含指向“global”的每个标签的链接。在helloworld这个示例中,我们必须将“_start”声明为全局,因为代码必须正确链接。原文:https://www.cnblogs.com/yungyu16/p/13024485.html