2014-12-22 49 views
1

我目前正在研究计算5阶乘的简单SPARC汇编代码。我想知道为什么我使用的全局寄存器通过函数调用不一致。Sparc程序集 - 整个函数调用中的全局寄存器不一致

随着使用的局部寄存器和输入/输出参数traditionnal版本(进入%O0),我没有问题,代码工作正常,

,但是当我想用另一个版本与全球寄存器,我有这个一致性问题。

下面的代码:

.data 
.LLC0: .asciz "fact(5) = %d\n" 

.text 
.global main 

main: 
     save %sp, -96, %sp 

     set 5, %g1    ! value 5 into %g1 register 
     sethi %hi(.LLC0), %g2 
     or %g2, %lo(.LLC0), %o0 
     mov %g1, %o1 
     call printf 
     nop 

     mov %g1, %o0    ! set %g1 into parameter for fact function 
     call fact 
     nop 

     mov %o0, %g4 
     sethi %hi(.LLC0), %g3 
     or %g3, %lo(.LLC0), %o0 
     mov %g4, %o1 
     call printf 
     nop 
     ret 

fact: 
     addcc %g1, -1, %g1  ! current index of the procedure - 
           ! supposed to be decremented at each call - 
     be term     ! PROBLEM : %g1 always set to 0 before decrement 
     nop 

     sethi %hi(.LLC0), %g2 
     or %g2, %lo(.LLC0), %o0 
     mov %g1, %o1 
     call printf    ! printf the value of %g1 : 
           ! still equal to -1 at execution 
     nop 

     call fact 
     nop 
     mov %o0, %g2 
     umul %g2, %g1, %g2 
     mov %g2, %i0 
     ret 

term: set 1, %o0 
     ret 

我的问题是,为fact功能,全局寄存器%g1设置为0在每次呼叫,使%g1打印在执行总是-1给人。

从这个link,我认为全球寄存器呈持续整个函数调用,即它们的范围是全球性的,并通过在代码中的任何功能的共享。

例如,在这里,我把set 5, %g1放在主要部分,通常我应该得到4作为fact函数的打印值。

如果任何人都可以看到什么是错的?

感谢

UPDATE:

调用printf使用%O0和01%,而不是%G1。我仍然有全局寄存器的范围(%G5-G7)的问题。下面是使用它们的例子是这样的:

.data 
.LLC0: .asciz "fact(5) = %d\n" 

.text 
.global main 

main: 
     save %sp, -120, %sp 

     set 5, %g5 
     sethi %hi(.LLC0), %g2 
     or %g2, %lo(.LLC0), %o0 
     mov %g5, %o1 
     call printf 
     nop 

     mov %g5, %o0 
     call fact 
     nop 

     mov %o0, %g7 
     sethi %hi(.LLC0), %g3 
     or %g3, %lo(.LLC0), %o0 
     mov %g7, %o1 
     call printf 
     nop 
     ret 
     restore 

fact: 
     addcc %g5, -1, %g5 
     be term 
     nop 

     sethi %hi(.LLC0), %g2 
     or %g2, %lo(.LLC0), %o0 
     mov %g5, %o1 
     call printf 
     nop 

     call fact 
     nop 
     mov %o0, %g6 
     smul %g6, %g5, %g6 
     mov %g6, %o0 
     ret 

term: set 1, %o0 
     ret 

在这段代码中,我打印的global %g5 register值在每次递归调用,输出为:

fact(5) = 5 
fact(5) = 838860799 
fact(5) = 838860798 
fact(5) = 838860797 
fact(5) = 838860796 
fact(5) = 838860795 
fact(5) = 838860794 
fact(5) = 838860793 
fact(5) = 838860792 
fact(5) = 838860791 
fact(5) = 838860790 
... 

好像从事实的第一个电话主要使初始值为%g5(初始化为5

我的错误在哪里?

感谢

回答

1

从SPARC汇编语言参考手册(https://docs.oracle.com/cd/E26502_01/html/E28387/toc.html

6.2寄存器使用

全局寄存器%g0-%G7更加复杂。 %g0寄存器始终为零。该%G6和G7%,始终保留操作系统,所以汇编代码不应该对其进行修改。其他全局寄存器,%g1-%g5,调用者保存,并可供应用程序代码使用。但请注意,%g1和%g5可用于程序链接表(PLT)或其他插入代码中,因此不能用于将参数从调用者传递给被调用者。

(我的重点)

我觉得你的问题是,“整个功能一致称之为”指调用和返回指令(等)不影响寄存器(用寄存器窗口切换),但调用约定确实允许被调用者更改寄存器,因此内容可能无法通话。

0

%g1 - %g4 are volatile - 你到printf呼叫占优你把%g1更早的价值,因为printf的实现也使用它。

相关问题