Mik*_*wan 10
系统调用用于从内核请求服务.对于MIPS,服务号/代码必须在$ v0中传递,并且参数在一些其他指定的寄存器中传递.例如,要打印我们可能会这样做:
li $v0, 1
add $a0, $t0, $zero
syscall
Run Code Online (Sandbox Code Playgroud)
在这种情况下,1是打印整数的服务代码.第二条指令有效地执行从$ t0到$ a0的复制,这是保存参数的指定寄存器(在这种情况下,是要打印的整数).提供了服务列表和相应的参数:http: //courses.missouristate.edu/KenVollmar/Mars/Help/SyscallHelp.html
当你走出像MARS或SPIM这样的仿真器的上下文时系统调用有点人为,这一点就变得更加明显了.在真正的MIPS机器上,您将使用它来转移控制内核来调用特定的函数.
例如,这是一个用于Linux机器的MIPS 32位程序集的基本hello world程序(我95%确定这是在mipsel安装上,而不是这个问题很重要)
# CS341L Fall 2008
# Lab Exercise #1
# Matthew J. Barrick <barrick@cs.unm.edu>
#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
Run Code Online (Sandbox Code Playgroud)
这与C代码非常接近(如果您在遵循MIPS程序集时遇到问题).
#include <stdio.h>
int main(int argc, char** argv) {
char* hello = "Hello World\n";
write(STDOUT_FILENO,hello, 12);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这头被包含给寄存器符号名(ASM/regdef.h),并且将在符号名称扳为系统调用(SYS/syscall.h)的标题,所以我们不必指系统调用第一个音符按号码.在这里进行系统调用的约定与调用函数,使用参数加载#register几乎相同,然后我们将所需的系统调用加载到$ v0并调用syscall.SYS_write对应于linux/unix的基本write(2)函数(1是标准输出).
ssize_t write(int fd, const void *buf, size_t count);
Run Code Online (Sandbox Code Playgroud)
所以我们告诉内核使用长度字节写入文件句柄1(stdout),字符串hello.在Linux上,你可以看到系统调用(2)所有不同的系统调用可用,但他们几乎对应内核提供核心功能和(G)的libc无论是包装还是建立在对C/C++程序.
Linux(以及大多数unix-like返回4BSD路由)都有一个函数syscall(2)实际上是同一个东西.
一旦你开始做更复杂的东西,你会发现自己将syscall调用包装到方便的函数中,或者更好的是只调用相应的libc版本(非常容易做到,但另一个讨论).