ser/usys.S 中用于 xv6 os 的系统调用程序集

syscall assembly in ser/usys.S for the xv6 os

user/usys.S这里有一个由usys.pl script

生成的片段
.global sbrk
sbrk:
 li a7, SYS_sbrk
 ecall
 ret
.global sleep
sleep:
 li a7, SYS_sleep
 ecall
 ret
.global uptime
uptime:
 li a7, SYS_uptime
 ecall
 ret

用户函数需要调用内核系统调用,因为只有内核才有权限执行所需的指令。 所以用户函数需要写成汇编,这样才能使用riscv ecall指令触发内核函数。 如何将参数传递给此内核系统调用函数?

我们就来说说sleep吧。在您之前的一个问题中,您将 link 发布到 user.h header file。 该头文件告诉您的 C 编译器函数采用什么参数以及函数 returns,在这一行:

int sleep(int);

处理该行后,C 编译器知道 sleep 需要单个 int 参数。因此,当您尝试在 C 程序中调用该函数时,编译器将确保使用向您平台上的函数传递 int 参数的标准方式将参数传递给该函数。这叫做calling convention。例如,调用约定可能会说将参数放入堆栈或将其放入特定寄存器。您可以查看 C 编译器生成的程序集,了解它在调用 sleep.

时做了什么

我真的不知道 ecall 做什么的细节,但在某些时候它应该会触发你内核中的一些代码,并且这些代码也会知道你的平台的调用约定,所以它可以检索您的 C 编译器传递给 sleep.

的参数

有关内核端的更多详细信息,请查看 the source code of sys_sleep 并了解它如何调用 argint 来获取其参数。