Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 参数数目不定的函数MIPS_Assembly_Mips_Mars Simulator - Fatal编程技术网

Assembly 参数数目不定的函数MIPS

Assembly 参数数目不定的函数MIPS,assembly,mips,mars-simulator,Assembly,Mips,Mars Simulator,我是MIPS的新手,如果这是个愚蠢的问题,请原谅。 我的任务是做以下练习,如果有任何想法和出发点,我将不胜感激 我应该创建一个函数,它接收参数n(数字的数量),然后接收n个数字,然后处理返回所述数字的总和,并在堆栈中返回它。 我怎么开始呢?我认为这个函数可能有4个以上的数字,而实际数字的数量不同这一事实让我感到困惑。 函数参数应该如下所示:(int n,int number1,int number2…等等) 我是否可以将数字存储在堆栈中,然后将堆栈用作函数中的参数?如果是,我会怎么做 更新: 因

我是MIPS的新手,如果这是个愚蠢的问题,请原谅。 我的任务是做以下练习,如果有任何想法和出发点,我将不胜感激

我应该创建一个函数,它接收参数n(数字的数量),然后接收n个数字,然后处理返回所述数字的总和,并在堆栈中返回它。 我怎么开始呢?我认为这个函数可能有4个以上的数字,而实际数字的数量不同这一事实让我感到困惑。 函数参数应该如下所示:(int n,int number1,int number2…等等)

我是否可以将数字存储在堆栈中,然后将堆栈用作函数中的参数?如果是,我会怎么做

更新: 因此,我现在的想法(在我得到的帮助下)是这样的:

sum:
addu $t3,$sp,16   #add to t3 address of sp+16
addu $a1,$a1,$a2   #adding sum to a1,a1 is first element a2 second and a3 third
addu $a1,$a1,$a3
li $t0,4          #start with i=4
bge $t0,$a0,end_for   #while i<n
lw $v0,0($t3)     #load v0 with value in stack
addu $a1,$v0,$a1  #add to sum
addi $t3,$t3,4   #increment stack and go up for next element
addi $t0,$t0,1
end_for:
li $v0,1
move $a0,$a0
syscall
jr $ra
sum:
添加$t3,$sp,16#添加到sp+16的t3地址
addu$a1,$a1,$a2#将总和加在a1上,a1是第一个元素,a2是第二个元素,a3是第三个元素
加成$a1、$a1、$a3
li$t0,4#从i=4开始

bge$t0,$a0,end_for#而在正常的MIPS调用约定中,第4个之后的args将已经存储在调用堆栈上,由调用方放置在那里

标准的调用约定在堆栈arg之前保留填充,您可以在其中存储寄存器arg以创建所有arg的连续数组,另见

这在x86-64 Windows中通常称为“阴影空间”。但由于MIPS
jal
不将任何内容存储到内存中(不像x86在堆栈上推送返回地址,MIPS将返回地址放在
$lr
中),即使调用约定不包括此阴影空间,函数仍然可以先调整SP,然后存储与堆栈参数相邻的寄存器参数。因此,我能看到的唯一好处是,在不必调整堆栈指针的情况下,为微小的函数提供额外的暂存空间。这不如在x86-64上有用,因为在x86-64上,不使用它就很难创建arg数组


或者,您可以剥离处理
$a1
的前3个求和迭代
$a3
(再次假设寄存器中前4个参数的标准MIPS调用约定,
$a0
int n

然后,如果还没有执行
n
,则循环堆栈参数


您可以编写一个C函数并查看优化的编译器输出,如下所示

#include <stdarg.h>
int sumargs(int n, ...) {
    va_list args;
    va_start(args, n);

    int sum=0;
    for (int i=0 ; i<n ; i++){
        sum += va_arg(args, int);
    }
    va_end(args);
    return sum;
}

在(--n)
时在
do{}上循环会更有效。在编译for循环时,gcc没有这样做,这是一个遗漏的优化。

在正常的MIPS调用约定中,第4个之后的arg将已经存储在调用堆栈上,由调用方放在那里

标准的调用约定在堆栈arg之前保留填充,您可以在其中存储寄存器arg以创建所有arg的连续数组,另见

这在x86-64 Windows中通常称为“阴影空间”。但由于MIPS
jal
不将任何内容存储到内存中(不像x86在堆栈上推送返回地址,MIPS将返回地址放在
$lr
中),即使调用约定不包括此阴影空间,函数仍然可以先调整SP,然后存储与堆栈参数相邻的寄存器参数。因此,我能看到的唯一好处是,在不必调整堆栈指针的情况下,为微小的函数提供额外的暂存空间。这不如在x86-64上有用,因为在x86-64上,不使用它就很难创建arg数组


或者,您可以剥离处理
$a1
的前3个求和迭代
$a3
(再次假设寄存器中前4个参数的标准MIPS调用约定,
$a0
int n

然后,如果还没有执行
n
,则循环堆栈参数


您可以编写一个C函数并查看优化的编译器输出,如下所示

#include <stdarg.h>
int sumargs(int n, ...) {
    va_list args;
    va_start(args, n);

    int sum=0;
    for (int i=0 ; i<n ; i++){
        sum += va_arg(args, int);
    }
    va_end(args);
    return sum;
}

在(--n)
时在
do{}上循环会更有效。gcc在编译for循环时没有这样做,这是一个遗漏的优化。

你确定教授不是要你使用数组吗?您可以使用varadic函数来实现,但是如果调用约定在寄存器中传递第一个参数,并且堆栈中没有归位,那么实现需要一些预处理,否则会变得混乱。MIPS在寄存器中传递第一个参数,其余参数在堆栈中传递而不返回原点(我想),因此最好在注册到varadic实现之前先弄清楚n个数字是如何传递的。@MargaretBloom是的,他说它应该相当于C中的add(3,1,2,3),add(2,1,5)(第一个参数告诉我们后面会有多少个数字)@MargaretBloom:MIPS使用链接寄存器而不是推送返回地址,因此您可以将寄存器arg与堆栈arg连续存储以形成一个arg数组。事实上,它也会像Windows x64一样留下阴影空间。可能如此小的函数可以节省对堆栈指针的操作?例如,它们可以在那里存储
$lr
在调用另一个函数之前?但是没有,他们必须为被调用方保留阴影空间,所以我认为这只对需要溢出某些内容的叶函数有帮助。看起来这是一个糟糕的设计(特别是与具有红色区域相比)。也许是一些放松的约定?@PeterCordes关于
$lr
的观点很好。事实上,我并不期望MIPS有阴影/主空间。总之,这比预期的要容易。@MargaretBloom:是的,我也很惊讶地发现它有阴影/主空间,就像我在回答中说的。没有阴影/主空间,它已经很小了,与x64不同,它的价值要低得多(我认为红色区域会是更好的选择)。但即使没有红色区域,剥离前3次迭代也很容易。或者是一个单独的带有2个循环的数组,或者完全剥离/展开。你确定教授不是要你使用数组吗?Y