I am currently working on a simple SPARC assembly code which computes the factorial of 5. I would like to know why the global registers that I used are not consistent througout function calls.
With the traditionnal version using of local registers and the output/input parameters (into %o0), I have no problem, the code works fine,
but when I want to use another version with global registers, I have this issue of consistency.
Here's the code :
.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
My problem is that, into fact
function, the global register %g1
is set to 0
at each call, so that the print of %g1
gives always -1
at execution.
From this link, I thought that global registers were persistent throughout functions call, i.e their scope were global and shared by any function in the code.
For example, here, I put set 5, %g1
in main section and normally, I should get 4
for the printed value in fact
function.
If anyone could see what's wrong ?
Thanks
UPDATE:
call printf uses %o0 and %o1, not %g1. I still have problems with the scope of global registers (%g5-g7). Here is an example using them like this :
.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
In this code, I print the value of global %g5 register
at each recursive call and the output is :
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
...
seems like the first call of fact from main make lose the initial value for %g5
(initialized to 5
)
Where is my error ?
Thanks
From the SPARC Assembly Language Reference Manual (https://docs.oracle.com/cd/E26502_01/html/E28387/toc.html)
6.2 Register Usage
(my emphasis)
I think your problem is that "Consistent throughout functions call" means that the call and return instructions (et al) do not affect the registers (with register window shifting) but that the calling convention does allow the callee to alter the registers, and hence the contents may not survive a call.