MIPS 架构“系统调用”指令

问题描述 投票:0回答:2

MIPS中syscall指令的作用是什么?

mips system-calls mips32 mips64
2个回答
14
投票

syscall 用于向内核请求服务。对于 MIPS,服务编号/代码必须在 $v0 中传递,参数在其他一些指定寄存器中传递。例如,要打印我们可能会这样做:

li $v0, 1
add $a0, $t0, $zero
syscall

在本例中,1 是打印整数的服务代码。第二条指令有效地执行从 $t0 到 $a0 的复制,$a0 是保存参数的指定寄存器(在本例中是要打印的整数)。 MARS 中可用的 SYSCALL 函数中给出了服务和相应参数的列表。


8
投票

当您走出像 MARSSPIM 这样的模拟器的上下文时,它会变得更加明显,其中系统调用有些人为。在真正的 MIPS 机器上,您可以使用它转移控制内核来调用特定函数。

例如,这是 Linux 机器上 MIPS 32 位程序集中的一个基本的 Hello, World! 程序(我 95% 确定这是在 mipsel 安装上,尽管对于这个问题来说这并不重要):

# CS341L Fall 2008
# Lab Exercise #1
# Matthew J. Barrick <[email protected]>

#include <asm/regdef.h>
#include <sys/syscall.h>

.data
    hello:  .asciz    "Hello World\n"
    length: .word    12
.text
    .globl  main
    .ent    main
main:
    li      a0, 1
    la      a1, hello
    lw      a2, length
    li      v0, SYS_write
    syscall
    move    v0, zero
    jr      ra
    .end    main

这与 C 代码非常接近(如果您在遵循 MIPS 汇编时遇到困难)。

#include <stdio.h>

int main(int argc, char** argv) {
    char* hello = "Hello, World\n";
    write(STDOUT_FILENO, hello, 12);
    return 0;
}

首先请注意,包含的标头是为了给寄存器提供符号名称(asm/regdef.h),以及一个将为系统调用引入符号名称的标头(sys/syscall.h),所以我们不这样做必须按编号引用系统调用。这里进行系统调用的约定与调用函数几乎相同,用参数加载a#寄存器,然后将我们想要的系统调用加载到$v0中并调用syscallSYS_write 对应于 Linux/Unix 的基本 write(2) 函数(1 是标准输出)。

ssize_t write(int fd, const void *buf, size_t count);

因此,我们告诉内核使用长度字节写入文件句柄 1(标准输出)、字符串 Hello。在 Linux 上,您可以看到 syscalls(2) 表示所有可用的不同系统调用,但它们几乎对应于内核提供的核心函数,并且 (g)libc 要么包装或构建 C/C++ 程序。

Linux(以及大多数类 Unix 系统,回到 4BSD 路线)有一个函数 syscall(2),它实际上是相同的东西。

一旦你开始做更复杂的事情,你会发现自己将 syscall 调用包装成方便的函数,或者更好的是只调用相应的 libc 版本(令人惊讶地容易做到,但另一个讨论)。

© www.soinside.com 2019 - 2024. All rights reserved.