What is the role of syscall instruction in MIPS?
The syscall is used to request a service from the kernel. For MIPS, the service number/code must be passed in $v0 and arguments are passed in a few of the other designated registers. For example, to print we might do:
li $v0, 1
add $a0, $t0, $zero
syscall
In this case, 1 is the service code for print integer. The second instruction effectively performs a copy from $t0 to $a0 which is the designated register where the argument is held ( in this case, the integer to be printed ). A list of the services and corresponding arguments is given in SYSCALL functions available in MARS.
It becomes a lot more obvious when you step outside the context of an emulator like MARS or SPIM where the system calls are somewhat artificial. On a real MIPS machine, you would use it transfer control the kernel to invoke a specific function.
For example, this is a basic Hello, World! program in MIPS 32-bit assembly for a Linux machine (I'm 95% sure this was on a mipsel install, though not that it matters much for this question):
# 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
This corresponds very closely to the C code (if you have trouble following the MIPS assembly).
#include <stdio.h>
int main(int argc, char** argv) {
char* hello = "Hello, World\n";
write(STDOUT_FILENO, hello, 12);
return 0;
}
First note that headers are included to give the registers symbolic names (asm/regdef.h) and a header that will pull in symbolic names for the system calls (sys/syscall.h), so we don't have to refer to the system calls by number. The conventions for making a system call here are pretty much the same as calling a function, load the a# register with arguments, and then we load which system call we want into $v0 and invoke syscall. SYS_write corresponds to the basic write(2) function for Linux/Unix (1 being standard output).
ssize_t write(int fd, const void *buf, size_t count);
So we're telling the kernel to write to the file handle 1 (standard output), the string Hello, using length bytes. On Linux you can see syscalls(2) for all the different system calls available, but they pretty much correspond the core functions that the kernel provides and that (g)libc either wraps or builds upon for C/C++ programs.
Linux (and most Unix-like systems, going back to the 4BSD route) have a function syscall(2) which is effectively the same thing.
Once you start doing more complex stuff, you'll either find yourself wrapping the syscall invoking into handy functions, or better yet just calling the corresponding libc versions (surprisingly easy to do, but another discussion).
© 2022 - 2024 — McMap. All rights reserved.