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"
SYSCALL_EXIT=1
SYSCALL_WRITE=4
STDOUT=1
.section ".text"
.globl main
/***********************************************************************/
main: save %sp, -96, %sp
mov 99, %l0 ! put the bottles onto the wall
loop: call putbtl
mov %l0, %o0 ! delay slot
sethi %hi(.strg1), %o0
call puts
or %o0, %lo(.strg1), %o0
call putbtl
mov %l0, %o0
sethi %hi(.strg2), %o0
call puts
or %o0, %lo(.strg2), %o0
cmp %l0, 0
be oob ! out of beer
dec %l0 ! n - 1
sethi %hi(.strg3), %o0
call puts
or %o0, %lo(.strg3), %o0
call putbtl
mov %l0, %o0
sethi %hi(.strg4), %o0
call puts
or %o0, %lo(.strg4), %o0
ba loop
nop
oob: sethi %hi(.strg5), %o0 ! no beer anymore
call puts
or %o0, %lo(.strg5), %o0
call exit
mov 0, %o0 ! exit code
/***********************************************************************
* print "n bottle(s)"/"no bottles" string, number in o0
*/
putbtl: save %sp, -96, %sp
cmp %i0, 1
ble 1f
nop
call putn ! > 1 bottle
mov %i0, %o0
sethi %hi(.botl2), %o0
call puts
or %o0, %lo(.botl2), %o0
ret
restore
1: cmp %i0, 0
be 1f
nop
call putn ! = 1 bottle
mov %i0, %o0
sethi %hi(.botl1), %o0
call puts
or %o0, %lo(.botl1), %o0
ret
restore
1: 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
udiv %i0, 10, %o0 ! o0 = i0 / 10
umul %o0, 10, %o2 ! o2 = o0 * 10
sub %i0, %o2, %o2 ! o2 = i0 - o2 => remainder
cmp %o0, 0 ! if quotient is not 0, we call
bz 1f ! putn recursively with
nop ! quotient as parameter.
call putn
nop
1: add %o2, 0x30, %o2 ! convert remainder to ascii
stb %o2, [%sp + 96] ! store remainder to stack
add %sp, 96, %o1 ! put stack address into o1
mov STDOUT, %o0
call write ! print remainder to stdout
mov 1, %o2 ! one character only
ret
restore
/***********************************************************************
* print zero terminated string, o0: string pointer
*/
puts: save %sp, -96, %sp
mov %i0, %o0
1: ldub [%o0], %o1 ! load next byte from buffer
cmp 0, %o1
bne,a 1b ! ,a: inc instruction is only
inc %o0 ! executed if branch is taken
sub %o0, %i0, %o2 ! strlen is in o2 now
mov %i0, %o1
call write
mov STDOUT, %o0
nop
ret
restore
/***********************************************************************
* write syscall, o0: fd, o1: string pointer, o2: length
*/
write: mov SYSCALL_WRITE, %g1 ! syscall number passed in g1
ta 8
retl
nop
/***********************************************************************
* exit syscall, exit code in o0
*/
exit: mov SYSCALL_EXIT, %g1
ta 8