具有多个参数的MIPS函数

时间:2016-06-08 16:12:19

标签: function mips32 qtspim

我知道如何在MIPS中创建一个接收4个参数的函数,因为我知道我可以将参数放入寄存器$ a0- $ a3。但是假设你想要超过4个参数,你如何解决MIPS中只有4个参数寄存器的事实($ a0- $ a3)?

1 个答案:

答案 0 :(得分:0)

有几种不同的方法可以做到这一点,每种方法都有自己的权衡:(1)使用mip ABI,(2)使用自己的内部寄存器约定,或(3)使用类似C的结构

mips ABI:

mips ABI [和大多数其他拱门一样],当你用完参数寄存器时,剩下的参数被压入堆栈。

考虑以下C程序:

params.map ( p => FutureWhichWontStartUnlessAskedWhichWrapsOtherFuture { dbQuery(p) }).findFirst(!_.isEmpty())

等效的mip ABI看起来像:

void
callee(int a,int b,int c,int d,int e,int f)
{
}

void
caller(void)
{
    int a;
    int b;
    int c;
    int d;
    int e;
    int f;

    callee(a,b,c,d,e,f);
}

自包含功能:

如果您的功能是自包含在程序中的[即你没有调用外部ABI符合函数],你可以在你希望的任何寄存器中传递参数:

caller:
    addiu   $sp,$sp,-8              # space for e,f

    lw      $t0,f
    sw      $t0,4($sp)

    lw      $t0,e
    sw      $t0,0($sp)

    lw      $a3,d
    lw      $a2,c
    lw      $a1,b
    lw      $a0,a

    jal     callee
    addiu   $sp,$sp,8               # remove space for e,f

    jr      $ra

callee:
    addiu   $sp,$sp,-4
    sw      $ra,0($sp)

    move    $t0,$a0                 # get a
    move    $t1,$a1                 # get b
    move    $t2,$a2                 # get c
    move    $t3,$a3                 # get d
    lw      $t4,4($sp)              # get e
    lw      $t5,8($sp)              # get f

    # ...

    lw      $ra,0($sp)
    addiu   $sp,$sp,4
    jr      $ra

使用C结构:

就像在C中一样,你可以在结构中传递很多东西:

caller:
    lw      $s7,f
    lw      $s6,e

    lw      $a3,d
    lw      $a2,c
    lw      $a1,b
    lw      $a0,a

    jal     callee

    jr      $ra

callee:
    addiu   $sp,$sp,-4
    sw      $ra,0($sp)

    move    $t0,$a0                 # get a
    move    $t1,$a1                 # get b
    move    $t2,$a2                 # get c
    move    $t3,$a3                 # get d
    move    $t4,$s6                 # get e
    move    $t5,$s7                 # get f

    # ...

    lw      $ra,0($sp)
    addiu   $sp,$sp,4
    jr      $ra

C结构的asm等价物用于等同于基址寄存器的偏移量:

struct args {
    int a;
    int b;
    int c;
    int d;
    int e;
    int f;
};

void
callee(struct args *av)
{
    int tmp;

    tmp = av->a;
    tmp = av->b;
    tmp = av->c;
    tmp = av->d;
    tmp = av->e;
    tmp = av->f;
}

void
caller(void)
{
    struct args args;

    args.a = 1;
    args.b = 2;
    args.c = 3;
    args.d = 4;
    args.e = 5;
    args.f = 6;

    callee(&args);
}