MIPS における syscall 命令の役割は何ですか?
2 に答える
syscall は、カーネルからサービスを要求するために使用されます。MIPS の場合、サービス番号/コードは $v0 で渡す必要があり、引数は他の指定されたレジスタのいくつかで渡されます。たとえば、印刷するには次のようにします。
li $v0, 1
add $a0, $t0, $zero
syscall
この場合、1 は print integer のサービス コードです。2 番目の命令は、$t0 から $a0 へのコピーを効果的に実行します。$a0 は、引数が保持される指定されたレジスタです (この場合は、表示される整数)。サービスと対応する引数のリストは次のとおりです: http://courses.missouristate.edu/KenVollmar/Mars/Help/SyscallHelp.html
MARS や SPIM のような、システム コールが人工的なものであるエミュレータのコンテキストから一歩外に出ると、これはより明白になります。実際の MIPS マシンでは、これを使用してカーネルに制御を移し、特定の機能を呼び出します。
たとえば、これは Linux マシン用の MIPS 32 ビット アセンブリの基本的な hello world プログラムです (これが mipsel インストールであったことは 95% 確信していますが、この質問にとってはそれほど重要ではありません)。
# 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
これは、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) のシンボリック名を取り込むヘッダーが含まれていることに注意してください。したがって、syscalls を参照する必要はありません。番号で。ここでシステム コールを作成するための規則は、関数を呼び出すのとほぼ同じです。# レジスタに引数をロードし、必要なシステム コールを $v0 にロードして、syscall を呼び出します。SYS_write は、linux/unix の基本的な write(2) 関数 (1 は標準出力) に対応します。
ssize_t write(int fd, const void *buf, size_t count);
そのため、長さバイトを使用して、ファイル ハンドル 1 (stdout)、文字列 hello に書き込むようにカーネルに指示しています。Linux では、利用可能なすべての異なる syscall の syscalls(2) を見ることができますが、それらはカーネルが提供するコア関数とほぼ対応しており、(g)libc は C/C++ プログラム用にラップまたはビルドします。
Linux (および 4BSD ルートに戻るほとんどの unix ライク) には、事実上同じことである関数 syscall(2) があります。
より複雑なことを始めると、システムコール呼び出しを便利な関数にラップするか、対応する libc バージョンを呼び出すだけでよいことに気付くでしょう (驚くほど簡単に実行できますが、別の議論があります)。