简体   繁体   中英

MIPS architecture syscall instruction

系统调用指令在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: http://courses.missouristate.edu/KenVollmar/Mars/Help/SyscallHelp.html

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, not that it matters much for this question)

# 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

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 syscalls by number. The conventions for making a system call here are pretty much the same as calling a function, load a# register with arguments, 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 out).

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

So we're telling the kernel to write to the file handle 1 (stdout), the string hello, using length bytes. On linux you can see syscalls(2) for all the different syscalls 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-likes going back 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).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM