【问题标题】:MIPS syscall instructionMIPS 系统调用指令
【发布时间】:2013-12-03 07:31:47
【问题描述】:

我反汇编了一些 MIPS 机器代码,得到了下面的代码 sn-p。

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

我想知道syscall 0的含义。

我知道需要syscall 号码才能拨打syscall。并且 syscall 号码通过 由$v0 注册。

没有使用$v0,而只有syscall 0

这是否等于:

move   $v0, 0  
syscall 

?

【问题讨论】:

    标签: assembly mips system-calls


    【解决方案1】:

    是的,syscall 0 似乎只是li $v0,0; syscall 的助记符。至于syscall 0,这完全取决于MIPS 芯片在其中运行的平台。例如,我曾经在 PlayStation1 游戏上工作(是的,在过去……叹息……),我认为 syscall 被用来在专门的矢量单元上执行数学计算。

    你在哪个平台上工作?

    【讨论】:

    • 啊,糟了。 :) 我想这让我成为了一个老屁,但它确实看起来并不是很久以前的所有那个
    • 如果它是“li $v0,0; ​​syscall”的快捷方式,机器代码的长度将是 8 个字节(li = 4 个字节,syscall = 4 个字节)。但是“syscall 0”的机器码是 4 个字节:00 00 00 0C!
    • 我想我从这里得到了助记符信息:courses.missouristate.edu/kenvollmar/mars/help/syscallhelp.html
    【解决方案2】:

    查看了 MIPS 文档:

    MIPS32TM 程序员架构第二卷:MIPS32TM 指令集

    它说:

    格式:SYSCALL 6 MIPS32 (MIPS I) 目的:引发系统调用 异常描述:发生系统调用异常,立即并 无条件地将控制权转移到异常处理程序。这 代码字段可用作软件参数,但 异常处理程序仅通过加载 包含指令的内存字。

    看起来指令中确实有“立即位”,但用法是 太复杂,所以很少使用。反而: 系统调用 似乎组装一样 系统调用 0 而 $v0 则用于传递系统调用号。更简单、更快捷。

    “立即位”的使用似乎需要“旧方式”:使用返回地址作为指针,并对指令中的系统调用号进行位屏蔽/移位。

    [编辑] 也就是说:从处理器的角度来看,立即位是“无关紧要的”。

    【讨论】:

    • 嘿@turboscrew:不要发布3个单独的答案,而是将它们组合成一个答案并去掉多余的答案。如您所见,可以“编辑”您自己的答案,因此合并然后删除多余的答案非常容易。
    • 从现在开始,我会尽量在我的帖子中保持一致。
    【解决方案3】:

    没有。它等于这两条指令!

    MIPS 的“系统调用”指令总是使用立即数参数(不是寄存器)。如果您没有显式键入参数,汇编程序将隐式添加 0 作为参数。

    一个例子:

    如果您键入以下代码:

    move     $v0, 123
    syscall
    

    汇编器确实创建了以下代码:

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

    (一些汇编程序使用“ori”或类似指令而不是“addi”。)

    是否使用“syscall”参数取决于操作系统(或 MIPS 模拟器)。据我所知,Linux 和 SPIM 模拟器都忽略了“syscall”指令的参数,因此您不必在汇编程序中显式键入参数。

    为什么 $v0 没有初始化?

    有两种可能的原因:

    1. $v0 在执行给定的代码时已经初始化,因此不必再初始化了
    2. 所使用的操作系统不使用 $v0 寄存器进行系统调用

    您应该知道,“syscall”指令的功能取决于所使用的操作系统(或 MIPS 模拟器)。在 Linux 和 IRIX 下运行同一台 (!) 计算机,“syscall”指令的行为将完全不同!

    -- 编辑--

    “系统调用”指令的 20 位参数在许多第三方(例如大学)文档中未提及。它在 MIPS 官方文档中有所提及(例如在 MIPS R4000 CPU 手册,第 A-162 页)。

    顺便说一句:GNU 反汇编器将指令 0x0000000c(这正是您程序中的指令)反汇编为“syscall”而不是“syscall 0”(而 0x0000010c 被反汇编为“syscall 0x4”)。

    【讨论】:

    • "不,不等于这两条指令!" Psst:courses.missouristate.edu/kenvollmar/mars/help/syscallhelp.html我觉得你把助记符和指令混淆了。
    • @JimBuck:“syscall”和“syscall 0”在汇编时产生完全相同的二进制代码(指令 0xC)。这意味着“系统调用 0”与没有“0”的“系统调用”相同。用户的问题是“syscall 0”是否与“move $v0, 0”和“syscall”的组合相同。答案是:不,它没有做同样的事情。我知道有汇编程序助记符会产生两条机器指令(至少在 ARM 汇编程序中——我不了解 MIPS)。但是看看反汇编你会发现这里不是这种情况。
    【解决方案4】:

    系统调用 0 也不需要使用 $v0。 在过去,系统调用参数就像 “立即”,系统调用使用返回地址作为参数指针。

    [编辑] 我查了一下:MIPS Linux、SPIM 和 MARS 都使用 $v0。

    【讨论】:

      【解决方案5】:

      虽然这在理论上可以回答这个问题,但它会是 最好在此处包含答案的基本部分,并且 提供参考链接

      删除的帖子中有一个链接。

      关于 Linux(不是理论,而是非常多的实践):

      (来自: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)
      

      ...

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-07-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多