you*_*t13 9 c assembly sparc mov
我正在学习SPARC程序集,您可以在下面看到一个简单的示例.我有几个关于这个例子的问题,它显示了一个过程的传递参数.
在主要部分中,我设置5为第一个输入参数%o0和7第二个输入参数%o1.之后,我将这些寄存器的总和放入其中%o2.然后,我调用"测试"功能,我打印这个总和.
fmt0:
.asciz "%d\n"
.align 4
.global main
main:
save %sp, -64, %sp
mov 5, %o0
mov 7, %o1
add %o0, %o1, %o2
!st %o2, [%fp-4] for storing %o2 at adress %fp-4
call test
nop
ret
test:
mov %i2, %o1
!ld [%fp-4], %o1 for loading from %fp-4 into %o1
set fmt0, %o0
call printf
nop
ret
Run Code Online (Sandbox Code Playgroud)
使用上面的代码,它打印值"-273929364"而不是"12"(用gcc编译).
似乎" mov %i2, %o1"不起作用.我知道,%o2在主要部分寄存器成为%i2在调用的过程,但我为什么不能直接设置的值%i2到%o1寄存器这个" mov"指令?
第二个问题:如果我取消注释st %o2, [%fp-4]主要部分中的指令" "和d [%fp-4], %o1测试功能中的"l "和注释" mov %i2, %o1",它会正确打印"12".我们如何知道作为传递参数函数的正确偏移?
从我所看到的,%sp变成%fp了" save %sp, -64, %sp"之后?具有%fp相同的价值main section和test function?
最后,我在不同的例子中看到了指令" call function, 0"或" call printf, 0":为什么我必须在函数名称之后添加"0"?这是返回值(如同int main(void){ ... return 0;})?
谢谢你的帮助
Eld*_*mov 11
我知道主要部分中的%o2寄存器在调用过程中变为%i2,但为什么我不能用这个"mov"指令直接将%i2的值设置到%o1寄存器中?
%o寄存器只%i在完成之后save,通常在被调用的函数的开头.在您的示例中,test函数没有save/ restore.
它是save/ restore旋转寄存器窗口,而不是call/ ret.既然test不是叶子函数(它printf从里面调用),它必须有自己的寄存器窗口.所以你必须test使用save/ 包装函数restore:
test:
save %sp, -64, %sp
mov %i2, %o1
set fmt0, %o0
call printf
nop
ret
restore
Run Code Online (Sandbox Code Playgroud)
否则,您的参数仍可通过%i2,但无论如何代码都是错误的,因为call printf指令会破坏test存储的返回地址%o7.
关于编辑建议中的问题(BTW不这样做,请在评论中提问):
如果%o7在非叶子程序中被覆盖,如何规避这个问题?我认为我必须在另一个寄存器的非叶子程序的开头推动%o7并在结尾弹出它,即在嵌套程序的调用之后,是不是?
在非叶子程序的情况下没有问题:save/ restore做技巧.您可能会认为save是"批处理"推送:它为您提供了一个新的注册窗口 - 一组16个寄存器(8 %i+ 8 %l),它们在嵌套的过程调用中保留它们的值.因此,restore将您带回以前保存的窗口.
所有%o寄存器均可%i在新窗口中访问.也就是说,调用者将参数设置为%o0 .. %o5(最多6个,因为%o6%和%o7是为堆栈指针和返回地址保留的).Callee制作save并获得了参数%i0 .. %i5.如果它想要返回一个值,它会将其放入%i0.返回后restore,调用者可以看到返回值(如果有)%o0.
这也回答了另一个你的问题:
从我看到,%sp在"save%sp,-64,%sp"指令后成为%fp?在主要部分和测试功能中%fp具有相同的值吗?
%sp只是别名%o6,而且%fp- for %i6.除了旋转窗口,save还可以像顺序add指令一样添加值.save %sp, -64, %sp意味着:取一个值,%sp旧的窗口,窗口旋转(%sp变%fp),加-64至该值并把结果变成%sp一个的新窗口.
换一种说法,
save %sp, -64, %sp
Run Code Online (Sandbox Code Playgroud)
做同样的事
save
add %fp, -64, %sp ! notice that the source register is now %fp, not %sp
Run Code Online (Sandbox Code Playgroud)
BTW,-64就是寄存器窗口的大小(16个寄存器,每个4个字节).它是负面的,因为堆栈增长了.
这是一个很好的答案,解释了SPARC寄存器窗口的概念.
刚刚注意到你的"寻找可靠和/或官方来源的答案"声明.SPARC v8架构手册是必读的,特别是涉及延迟槽,寄存器窗口,叶子程序优化和软件考虑因素的章节.