This is the "99 bottles of beer" program coded in SPARC assembly language. The program tries to demonstrate some special features of the SPARC processor like delay slots, anulled delay slots and system calls.
The below code has been submitted to http://www.99-bottles-of-beer.net and can be found on this page. You can also download the code here.
/***********************************************************************
* 99 Bottles of Beer in SPARC assembly language for Sun Solaris
* Compile with: as -o bottles.o bottles.s; ld -o bottles bottles.o
***********************************************************************/
.section ".rodata"
.align 4
.botl0: .asciz "no more bottles"
.botl1: .asciz " bottle"
.botl2: .asciz " bottles"
.strg1: .asciz " of beer on the wall, "
.strg2: .asciz " of beer.\n"
.strg3: .asciz "Take one down and pass it around, "
.strg4: .asciz " of beer on the wall.\n\n"
.strg5: .ascii "Go to the store and buy some more,"
.asciz " 99 bottles of beer on the wall.\n"
=1
SYSCALL_EXIT=4
SYSCALL_WRITE=1
STDOUT.section ".text"
.globl main
/***********************************************************************/
main: save %sp, -96, %sp
99, %l0 ! put the bottles onto the wall
mov loop: call putbtl
%l0, %o0 ! delay slot
mov %hi(.strg1), %o0
sethi call puts
or %o0, %lo(.strg1), %o0
call putbtl
%l0, %o0
mov %hi(.strg2), %o0
sethi call puts
or %o0, %lo(.strg2), %o0
%l0, 0
cmp ! out of beer
be oob dec %l0 ! n - 1
%hi(.strg3), %o0
sethi call puts
or %o0, %lo(.strg3), %o0
call putbtl
%l0, %o0
mov %hi(.strg4), %o0
sethi call puts
or %o0, %lo(.strg4), %o0
loop
ba nop
oob: sethi %hi(.strg5), %o0 ! no beer anymore
call puts
or %o0, %lo(.strg5), %o0
call exit
0, %o0 ! exit code
mov /***********************************************************************
* print "n bottle(s)"/"no bottles" string, number in o0
*/
putbtl: save %sp, -96, %sp
%i0, 1
cmp 1f
ble nop
call putn ! > 1 bottle
%i0, %o0
mov %hi(.botl2), %o0
sethi call puts
or %o0, %lo(.botl2), %o0
ret
restore1: cmp %i0, 0
1f
be nop
call putn ! = 1 bottle
%i0, %o0
mov %hi(.botl1), %o0
sethi call puts
or %o0, %lo(.botl1), %o0
ret
restore1: sethi %hi(.botl0), %o0 ! no bottles
call puts
or %o0, %lo(.botl0), %o0
ret
restore/***********************************************************************
* print number in o0 to stdout
*/
putn: save %sp, -(96 + 8), %sp ! we need some stack space here
%i0, 10, %o0 ! o0 = i0 / 10
udiv %o0, 10, %o2 ! o2 = o0 * 10
umul sub %i0, %o2, %o2 ! o2 = i0 - o2 => remainder
%o0, 0 ! if quotient is not 0, we call
cmp 1f ! putn recursively with
bz nop ! quotient as parameter.
call putn
nop
1: add %o2, 0x30, %o2 ! convert remainder to ascii
%o2, [%sp + 96] ! store remainder to stack
stb %sp, 96, %o1 ! put stack address into o1
add , %o0
mov STDOUTcall write ! print remainder to stdout
1, %o2 ! one character only
mov ret
restore/***********************************************************************
* print zero terminated string, o0: string pointer
*/
puts: save %sp, -96, %sp
%i0, %o0
mov 1: ldub [%o0], %o1 ! load next byte from buffer
0, %o1
cmp ,a 1b ! ,a: inc instruction is only
bneinc %o0 ! executed if branch is taken
sub %o0, %i0, %o2 ! strlen is in o2 now
%i0, %o1
mov call write
, %o0
mov STDOUTnop
ret
restore/***********************************************************************
* write syscall, o0: fd, o1: string pointer, o2: length
*/
write: mov SYSCALL_WRITE, %g1 ! syscall number passed in g1
8
ta
retlnop
/***********************************************************************
* exit syscall, exit code in o0
*/
exit: mov SYSCALL_EXIT, %g1
8 ta