정지훈
정지훈

Reputation: 41

MIPS syscall instruction

I disassembled some MIPS machine code and I got below code snippet.

00 00 00 0C             syscall 0                # System Call
00 00 00 00             nop
03 E0 00 08             jr      $ra              # Jump Register
00 00 00 00             nop

I want to know meaning of syscall 0.

I know syscall number is required to call a syscall. And the syscall number is passed by $v0 register.

There is no use of $v0 but only syscall 0

Is this equal to:

move   $v0, 0  
syscall 

?

Upvotes: 0

Views: 11075

Answers (5)

turboscrew
turboscrew

Reputation: 676

Checked the MIPS document:

MIPS32TM Architecture For Programmers Volume II: The MIPS32TM Instruction Set

and it says:

Format: SYSCALL 6 MIPS32 (MIPS I) Purpose: To cause a System Call exception Description: A system call exception occurs, immediately and unconditionally transferring control to the exception handler. The code field is available for use as software parameters, but is retrieved by the exception handler only by loading the contents of the memory word containing the instruction.

Looks like there really are "immediate bits" in the instruction, but the usage is too complicated, so it's seldom used. Instead: syscall seems to assemble the same as syscall 0 and the $v0 is used to pass the system call number instead. Easier and faster.

The use of the "immediate bits" seems to require the "old way": using the return address as a pointer and bit-masking/shifting the syscall number from the instruction.

[edit] That is: from the processor's point of view, the immediate bits are "don't care".

Upvotes: 2

turboscrew
turboscrew

Reputation: 676

Whilst this may theoretically answer the question, it would be preferable to include the essential parts of the answer here, and provide the link for reference

There was a link in the deleted post.

About Linux (not theory, but very much practice):

(from: http://lxr.linux.no/linux+v3.12.2/arch/mips/kernel/scall32-o32.S#L100 )

/* Highest syscall used of any syscall flavour */
  25#define MAX_SYSCALL_NO  __NR_O32_Linux + __NR_O32_Linux_syscalls
  26
  27        .align  5
  28NESTED(handle_sys, PT_SIZE, sp)
  29        .set    noat
  30        SAVE_SOME
  31        TRACE_IRQS_ON_RELOAD
  32        STI
  33        .set    at
  34
  35        lw      t1, PT_EPC(sp)          # skip syscall on return
  36
  37        subu    v0, v0, __NR_O32_Linux  # check syscall number
  38        sltiu   t0, v0, __NR_O32_Linux_syscalls + 1
  39        addiu   t1, 4                   # skip to next instruction
  40        sw      t1, PT_EPC(sp)

...

Upvotes: 0

Martin Rosenau
Martin Rosenau

Reputation: 18493

No. It is not equal to these two instructions!

The "syscall" instruction for MIPS always uses an immediate numeric argument (not a register). If you do not type an argument explicitly assemblers will implicitly add a 0 as argument.

An example:

If you type the following code:

move     $v0, 123
syscall

The assembler really creates the following code:

addi     $v0, $zero, 123   # MIPS CPUs do not have a "move" instruction
syscall  0                 # Implicit argument "0" added

(Some assemblers use "ori" or similar instructions instead of "addi".)

It depends on the operating system (or MIPS simulator) if the argument of "syscall" is used or not. As far as I know both Linux and the SPIM simulator ignore the argument of the "syscall" instruction so you do not explicitly type the argument in assembler programs.

And why is $v0 not initialized?

There are two possible reasons:

  1. $v0 is already initialized when the given piece of code is executed so it does not have to be initialized any more
  2. The operating system used does not use the $v0 register for system calls

You should be aware that the function of the "syscall" instruction depends on the operating system (or MIPS simulator) used. Running the same (!) computer under Linux and under IRIX the "syscall" instruction will behave completely differently!

-- EDIT --

The 20-bit argument of the "syscall" instruction is not mentioned in many third-party (e.g. university) documents. It is mentioned in the official MIPS documents (for example in the MIPS R4000 CPU manual, page A-162).

By the way: The GNU disassembler disassembles the instruction 0x0000000c (this is exactly the instruction from your program) as "syscall" and not as "syscall 0" (while 0x0000010c is disassembled as "syscall 0x4").

Upvotes: 1

turboscrew
turboscrew

Reputation: 676

Also syscall 0 doesn't need to use $v0. In older days it was quite common that the system call parameters were just like "immediates", and the system call uses the return address as parameter pointer.

[edit] I checked: MIPS Linux, SPIM and MARS all use $v0.

Upvotes: 0

Jim Buck
Jim Buck

Reputation: 20726

Yes, it would appear that syscall 0 is merely a mnemonic for li $v0,0; syscall. As for what is syscall 0, that's completely dependent on the platform the MIPS chip is running inside of. For example, I used to work on PlayStation1 games (yeah, back in the day.. sigh..), and I think syscall was used to execute math calculations on the specialized vector unit.

What platform are you working on?

Upvotes: 3

Related Questions