当前位置: 首页 > news >正文

x64汇编之系统调用详解

大家好,你们可以叫我凌,是个16岁的网络安全学习者。

我想了想,还是决定把系统调用单独拿出来讲讲,毕竟该内容为汇编语言的核心内容,极为重要。

内容可能会有点拗口,不过在文章最后我奉上了我的“焚决”,懂点网络安全的人应该立马就可以茅塞顿开

继上篇《x64汇编之从程序编辑到系统调用》,我们已经初步了解系统调用,这篇我们来进行更加细致的讲解。那话不多说,我们直接开始吧!


什么是系统调用

用户态与内核态

CPU 有两种运行状态

用户态:权限低,不能直接访问硬件、内核内存等。我们编写的普通程序运行在此状态。

内核态:权限高,可以执行任何指令。操作系统内核运行在此状态。

为什么需要系统调用

如果程序需要显示文字、读取键盘、打开文件、退出等操作,这些都属于特权操作,必须在内核态完成。因此,用户程序必须通过系统调用来请求内核代为执行。

类比:去银行取钱,不能自己打开金库(如果这样的话,他们可能会问“乍进来的?如此大胆”),必须填单子(参数)交给柜员(内核),柜员帮你操作。系统调用就是递给柜员的那张单子。

系统调用的过程

1.在特定寄存器中放入系统调用号(告诉内核你要做什么)和参数(告诉内核具体怎么做)

2.执行syscall指令。

3.CPU 切换到内核态,内核根据系统调用号调用相应函数,执行操作。

4.内核将结果(成功或失败)放回寄存器,CPU 切回用户态,程序继续执行。

系统调用的寄存器约定

在 x64 Linux 中,发起系统调用使用syscall指令,参数通过固定寄存器传递,返回值也通过寄存器返回。规则如下:

寄存器作用
rax系统调用号(调用前),返回值(调用后)
rdi第1个参数
rsi第2个参数
rdx第3个参数
r10第4个参数(注意:不是 rcx
r8第5个参数
r9第6个参数

说明

系统调用最多支持6个参数。超过6个的情况极少见,通过栈传递,现在无需关注。

在普通函数调用(如 C 语言)中,第4个参数是rcx,但系统调用固定使用r10。这是因为syscall指令会破坏rcxr11的值,因此内核选择用r10来避免冲突。

系统调用号速查表

系统调用号是定义在内核中的常量,可以在/usr/include/asm/unistd_64.h中查到所有定义。下表按功能分类,列出最常用的系统调用。

注意:mmap(调用号 9)实际需要 6 个参数,顺序为 rdi(地址建议)、rsi(长度)、rdx(保护标志)、r10(映射标志)、r8(文件描述符)、r9(偏移量)。其他系统调用参数较少,未使用的寄存器忽略即可。

参数详解

每个系统调用的参数都有特定的含义和取值范围。下面列出最常用的几个,并给出详细说明。

文件描述符(fd)

文件描述符是一个非负整数,代表一个已打开的文件或设备。程序启动时自动打开三个:

名称含义

0

stdin标准输入(通常是键盘)
1stdout标准输出(通常是屏幕)
2stderr标准错误(通常是屏幕)

其他文件描述符(如 3, 4)由open系统调用返回,代表打开的文件。

sys_write 与 sys_read 的参数

rdi:文件描述符(如 1 表示屏幕,0 表示键盘)。

rsi:数据缓冲区的地址。可以是.data段中定义的标签(如 msg),也可以是 .bss 中预留的空间。

rdx:要读取或写入的字节数。注意不要超过缓冲区实际大小,否则可能越界。

示例:向屏幕输出 hello(6字节)

mov rax, 1 mov rdi, 1 mov rsi, msg mov rdx, 6 syscall

sys_open 的打开标志(flags)

flags参数指定打开文件的方式,常用值如下(十六进制)

标志(十六进制)宏名称含义
0x0O_RDONLY只读
0x1O_WRONLY只写
0x2O_RDWR读写
0x200O_CREAT若文件不存在则创建
0x400O_TRUNC若文件存在则清空
0x800O_APPEND追加模式(写入从文件末尾开始)

多个标志可以用按位或组合,例如O_WRONLY | O_CREAT | O_TRUNC = 1 | 0x200 | 0x400 = 0x601

mode:当使用O_CREAT时,需要指定新文件的权限,通常用八进制表示,如0644(所有者读写,组和其他只读)。该值仅在创建文件时有效。

sys_exit 的退出码

退出码是一个 8 位整数(0~255),父进程可以通过wait系统调用获取。
约定:0 表示成功,非零表示错误(如 1 一般性错误,2 误用 shell 等)。可以自定义其他值。

sys_lseek 的 whence 参数

0SEEK_SET):从文件开头偏移

1SEEK_CUR):从当前位置偏移

2SEEK_END):从文件末尾偏移

偏移量offset可以是正数或负数(但通常为正)。

返回值与错误处理

系统调用执行成功后,返回值通常放在rax

sys_read返回实际读取的字节数(0 表示 EOF,-1 表示错误)

sys_write返回实际写入的字节数(-1 表示错误)

sys_open返回文件描述符(-1 表示错误)

sys_exit无返回值(程序终止)

错误处理:如果rax中的值为-1(即0xffffffffffffffff)则表示调用失败。具体的错误码可以通过errno获取。在汇编中,可以通过检查rax是否为负数来判断错误,但获取errno需要调用另一个系统调用(或使用 C 库)。通常只需检查返回值是否为-1,然后根据错误码做相应处理。

常见错误码(errno 值)

错误码名称含义
1EPERM操作不允许
2ENOENT文件或目录不存在
13EACCES权限拒绝
22EINVAL无效参数
24EMFILE打开文件过多
28ENOSPC磁盘空间不足

完整示例:输出 Hello 并成功退出

section .data msg db "Hello, World!", 10 ; 10 是换行符 LF len equ $ - msg ; 自动计算长度 section .text global _start _start: ; 1. 输出字符串 mov rax, 1 ; sys_write mov rdi, 1 ; stdout mov rsi, msg ; 字符串地址 mov rdx, len ; 长度 syscall ; 检查错误(通常 write 不会出错,但演示) cmp rax, 0 js error ; 如果 rax < 0,跳转到错误处理 ; 2. 正常退出 mov rax, 60 ; sys_exit mov rdi, 0 ; 成功 syscall error: ; 错误处理:退出码 1 mov rax, 60 mov rdi, 1 syscall

编译运行

nasm -f elf64 hello.asm -o hello.o
ld hello.o -o hello
./hello

常见问题与易混淆点

为什么 rax=0 不是成功,而是 sys_read?

rax存放的是系统调用号,不是退出码。成功退出是rax=60+rdi=0

为什么 rdi=1 有时是“标准输出”,有时是“退出码1”?

sys_write中,rdi是文件描述符,1表示标准输出。

sys_exit中,rdi是退出码,1表示错误。

上下文决定含义。

系统调用为什么用 r10 而不用 rcx?

因为syscall指令会破坏rcxr11的值(用于保存返回地址和标志位),所以第4个参数被分配到了r10

总结

要点说明
系统调用号放在rax中,告诉内核做什么
参数传递rdi,rsi,rdx,r10,r8,r9依次存放最多6个参数
返回值成功时返回值在rax,失败时rax = -1
错误码需要通过errno获取,汇编中通常只判断正负
常用调用sys_write(1)、sys_exit(60)是入门必须记住的

刚开始不必记忆所有系统调用号,只要记住1(写)和60(退出),其他用到时查表即可。多写代码,多调试,系统调用就会变得自然。

如果还是不明白,我这里还有套“焚决”

系统调用就像 MSF:rax选模块,rdi/rsi/rdx设参数,syscall执行

http://www.jsqmd.com/news/624659/

相关文章:

  • 【PolarCTF】system
  • AI技术变革下的SEO关键词优化新模式探索
  • 别再怪PaddleOCR了!可能是你的图片‘喂’得不对:聊聊OCR预处理的门道
  • 重构实战:如何识别并修复‘被拒绝的遗赠’代码异味
  • 【PolarCTF】简单溢出
  • Maomi.In | .NET 全能多语言解决方案乒
  • 如何轻松实现EMQX消息持久化?emqx_persistence_plugin完整指南
  • Burpsuite之暴力破解+验证码识别 | 添柴不加火辟
  • 【仅限首批200家认证企业开放】:基于ISO/IEC 23053标准的AI原生软件流水线成熟度评估矩阵(含自动打分CLI工具链)
  • 知识星球内容本地化:从云端依赖到个人知识库的转变
  • 如何让微信聊天记录成为你的个人数字资产?WeChatMsg完整解决方案
  • CAD工件图和实物图对比识别项目总结
  • 使用小龙虾来操作猿编程的遥控车懦
  • AI微服务治理为何频频崩溃?:揭秘OpenTelemetry+Istio在LLM推理链路中的7类隐性故障模式
  • X-AnyLabeling从源码到打包:一份给开发者的定制化部署指南(Windows/Linux/MacOS全平台)
  • 营销自动化数据驱动 - 多源数据 OLAP 架构演进胶
  • 为什么92%的AI原生应用在出海时本地化失败?——基于27个真实项目复盘的5维失效根因图谱
  • IDEA里用PlantUML画类图,为啥我装了插件还是不行?手把手教你搞定Graphviz配置
  • WindRunnerMax毖
  • Ryzen处理器SMU深度调试:5大核心技术原理与性能调优实战
  • 清北博雅考研:全科全阶全场景,真正一站式综合考研辅导标杆
  • 【C】顺时针螺旋移动法
  • 嵌入式c语言——关键字其6
  • Mac/Win双平台指南:最新VMware Fusion 13及Workstation Pro 17从博通官网下载全流程
  • 【央行科技司内部评估首曝】:AI原生支付系统已通过沙盒压力测试——但92%企业正因这4个认知盲区错失接入窗口期?
  • VBA-JSON终极指南:Excel数据与JSON格式互转的完整解决方案
  • Mermaid Live Editor:代码即图表的新一代可视化开发体验
  • Android Safety 系列专题【篇七:Android AVF机制】
  • fasdfsadfsda
  • 2025届必备的十大降重复率助手解析与推荐