SPARC Assembly Language Reference Manual

Exit Print View

Updated: July 2014
 
 

A Sample Assembler Program

The following code takes a sample C language program and generates the corresponding assembly code using the Oracle Solaris Studio C compiler running on the Solaris 11 operating environment. Comments have been added to the assembly code to show correspondence to the C code.

The following C Program computes the first n Fibonacci numbers.

Example B-1  C Program Example Source
#include <stdio.h>
#include <stdlib.h>

/* a simple program computing the first n Fibonacci numbers */

extern unsigned * fibonacci();

#define MAX_FIB_REPRESENTABLE 49

/* compute the first n Fibonacci numbers */
unsigned * fibonacci(n)
     int n;
{
  static unsigned fib_array[MAX_FIB_REPRESENTABLE] = {0,1};
  unsigned prev_number = 0;
  unsigned curr_number = 1;
  int i;

  if (n >= MAX_FIB_REPRESENTABLE) {
    printf("Fibonacci(%d) cannot be represented in a 32 bit word\n", n);
    exit(1);
  }

  for (i = 2; i < n; i++) {
    fib_array[i] = prev_number + curr_number;
    prev_number = curr_number;
    curr_number = fib_array[i];
  }

  return(fib_array);
}

int main()
{
  int n, i;
  unsigned * result;

  printf("Fibonacci(n):, please enter n:\n");
  scanf("%d", &n);

  result = fibonacci(n);
  for (i = 1; i <= n; i++)
    printf("Fibonacci (%d) is %u\n", i, *result);

  return 0;
}

The Oracle Solaris Studio C compiler generates the following assembler output for the Fibonacci number C source. Annotation has been added to help you understand the code.

Example B-2  Assembler Output From C Source
    .section    ".text",#alloc,#execinstr
    .file   "fib.c"

    .section    ".data",#alloc,#write       ! open a data section
                            ! #alloc - memory will be allocated for this section at runtime
                            ! #write - section contains data that is writeable during process execution
Ddata.data:
    .align  4                       ! align the beginning of this section to a 4-byte boundary

.L18:
    .skip   4                       ! skip 4 bytes, which initializes fib_array[0]=0
    .word   1                       ! write the 4-byte value '1', initializes fib_array[1]=1
    .skip   188                     ! skip 188 bytes, which initializes the remainder of fib_array[] to 0
    .type   .L18,#object                ! set the type of .L17 (fib_array) to be an object

Drodata.rodata:
    .section    ".rodata1",#alloc           ! open a read-only data section.
    .align  4

!
! CONSTANT POOL
!

.L21:
    .ascii  "Fibonacci(%d) cannot be represented in a 32 bit word\n\000"    ! ascii string for printf
    .align  4                                   ! align the next ascii string to a 4-byte boundary

.L34:
    .ascii  "Fibonacci(n):, please enter n:\n\000"
    .align  4

.L35:
    .ascii  "%d\000"
    .align  4

.L40:
    .ascii  "Fibonacci (%d) is %u\n\000"

    .section    ".text",#alloc,#execinstr       ! open a text section
/* 000000      0 */     .align  4
/* 000000        */     .skip   16
/* 0x0010        */     .align  4
! FILE fib.c

!    1        !#include <stdio.h>
!    2        !#include <stdlib.h>
!    4        !/* a simple program computing the first n Fibonacci numbers */
!    6        !extern unsigned * fibonacci();
!    8        !#define MAX_FIB_REPRESENTABLE 49
!   10        !/* compute the first n Fibonacci numbers */
!   11        !unsigned * fibonacci(n)
!   12        !     int n;
!   13        !{

!
! SUBROUTINE fibonacci
!
! OFFSET    SOURCE LINE LABEL   INSTRUCTION

            .global fibonacci           ! create a symbol with global scope

            fibonacci:

            .L900000112:
/* 000000     13 */     save    %sp,-96,%sp     ! create a new stack frame and
                            ! register window for this subroutine

!   14        !  static unsigned fib_array[MAX_FIB_REPRESENTABLE] = {0,1};
!   15        !  unsigned prev_number = 0;
!   16        !  unsigned curr_number = 1;
!   17        !  int i;
!   19        !  if (n >= MAX_FIB_REPRESENTABLE) {

/* 0x0004     19 */     cmp     %i0,49      ! cmp is a synthetic instr, equivalent to
                            ! subcc %i0,49,%g0
/* 0x0008        */     bge,pn  %icc,.L77000033 ! branch %i0 (n) on gt 49 to .L77000033 ;
!                                                 predict not taken
/* 0x000c     24 */     cmp     %i0,2       ! delay slot instr. Note that although
                            ! this instr is conceptually executed before the branch, it does
                            ! not influence the condition codes as seen by the branch

!   20        !    printf("Fibonacci(%d) cannot be represented in a 32 bit word\n", n);
!   21        !    exit(1);
!   22        !  }
!   24        !  for (i = 2; i < n; i++) {

            .L77000052:
/* 0x0010     24 */     ble,pn  %icc,.L77000043 ! branch on n less equal to 2 ;  predict not taken
/* 0x0014        */     mov     2,%l4       ! delay slot instr. %l4 = i = 2

            .L77000061:
/* 0x0018     24 */     add     %i0,-1,%l5          ! %l5 = %i0 (n) - 1
/* 0x001c     16 */     mov     1,%i4           ! %i4 (curr_number) = 1
/* 0x0020     15 */     mov     0,%i3           ! %i3 (prev_number) = 0
/* 0x0024        */     sethi   %hi(.L18),%i1       ! set the high 22-bits of %i1 to the address of .L18
                                ! (fib_array)
            .L900000109:
/* 0x0028     15 */     add     %i1,%lo(.L18),%i0       ! complete the formation of the address of fib_array

!   25        !    fib_array[i] = prev_number + curr_number;

/* 0x002c     25 */     add     %i3,%i4,%l7         ! %i7 = %i3 (prev_number) + %i4 (curr_number)
/* 0x0030     15 */     add     %i0,8,%l6           ! %l6 = &fib_array[i]

            .L900000110:
                                ! beginning of the loop body
/* 0x0034     24 */     add     %l4,1,%l4           ! increment i by 1

!   26        !    prev_number = curr_number;

/* 0x0038     26 */     mov     %i4,%i3         ! %i3 (prev_number) = %i4 (curr_number)
/* 0x003c     25 */     st      %l7,[%l6]           ! store %l7 into fib_array[i]

!   27        !    curr_number = fib_array[i];

/* 0x0040     27 */     mov     %l7,%i4         ! %i4 (curr_number) = %l7 (fib_array[i])
/* 0x0044     24 */     add     %l6,4,%l6       ! increase %l6 by 4 bytes, so that it now contains &fib_array[i+1]
/* 0x0048        */     cmp     %l4,%l5         ! i <= (n - 1)
/* 0x004c        */     ble,pt  %icc,.L900000110    ! if yes (predict taken), goto beginning of loop
/* 0x0050     25 */     add     %i3,%i4,%l7     ! delay slot instr. %i7 = %i3 (prev_number) + %l4 (curr_number)
                                ! end of loop body

!   28        !  }
!   30        !  return(fib_array);

                                ! Body of if (n >= MAX_FIB_REPRESENTABLE) {}
            .L77000043:
/* 0x0054     30 */     sethi   %hi(.L18),%i5       ! set the high 22-bits of %l4 to the address of .L18
                                ! (fib_array)
/* 0x0058     24 */     ret                 ! synthetic instr.  equivalent to jmpl %i7+8, %g0
/* 0x005c        */     restore %i5,%lo(.L18),%o0       ! delay slot instr. restore the caller's window.
                                ! the subroutine return value is in %o0

            .L77000033:
/* 0x0060     20 */     sethi   %hi(.L21),%i2       ! set the high 22-bits of %i2 to the address of .L21
                                ! (string to be passed to printf)
/* 0x0064     16 */     mov     1,%i4           ! ** note that the instrs marked "**" are unnecessary. These instrs
                                ! perform the same function as those earlier in the program. They are created
                                ! by the compiler as it is not aware that ( exit(1) ) will terminate the
                                ! program.
/* 0x0068     20 */     add     %i2,%lo(.L21),%o0   ! add high and low bits 
!                                  to complete formation of address of .L21
/* 0x006c     15 */     mov     0,%i3           ! **
/* 0x0070     20 */     call    printf  ! params =  %o0 %o1 ! Call printf with args  %o0 and %o1
/* 0x0074        */     mov     %i0,%o1
/* 0x0078     21 */     call    exit    ! params =  %o0     ! Call exit whose 1st arg is %o0
/* 0x007c        */     mov     1,%o0           ! **
/* 0x0080        */     add     %i0,-1,%l5          ! **
/* 0x0084     24 */     mov     2,%l4           ! **
/* 0x0088        */     ba      .L900000109         ! **
/* 0x008c     15 */     sethi   %hi(.L18),%i1       ! **

/* 0x0090      0 */     .type   fibonacci,#function     ! set the type of fibonacci to be a function
/* 0x0090      0 */     .size   fibonacci,(.-fibonacci) ! set the size of the function
                                ! size of function:
                                !   current location counter minus beginning definition of function


            .L900000113:

    .section    ".text",#alloc,#execinstr
/* 000000      0 */     .align  4

!   31        !}
!   33        !int main()
!   34        !{

!
! SUBROUTINE main
!
! OFFSET    SOURCE LINE LABEL   INSTRUCTION

            .global main

            main:

            .L900000210:
/* 000000     34 */     save    %sp,-104,%sp
/* 0x0004      0 */     sethi   %hi(.L34),%i5
/* 0x0008      0 */     add     %i5,%lo(.L34),%i1

!   35        !  int n, i;
!   36        !  unsigned * result;
!   38        !  printf("Fibonacci(n):, please enter n:\n");

/* 0x000c     38 */     call    printf      ! params =  %o0
/* 0x0010        */     mov     %i1,%o0

!   39        !  scanf("%d", &n);

/* 0x0014     39 */     add     %i1,32,%o0      ! %o0 = %i1+32 (&.L35)
/* 0x0018        */     call    scanf       ! params =  %o0 %o1
/* 0x001c        */     add     %fp,-4,%o1      ! %o1 = %fp-4 (&n)

!   41        !  result = fibonacci(n);

/* 0x0020     41 */     call    fibonacci       ! params =  %o0 ! Result =  %o0. On return from the
                            ! routine, %o0 = &fib_array
/* 0x0024        */     ld      [%fp-4],%o0     ! delay slot instr. load the value at %fp-4 (n) into %o0
/* 0x0028        */     ld      [%fp-4],%i4     ! load the value at %fp-4 (n) into %i4

!   42        !  for (i = 1; i <= n; i++)

/* 0x002c     42 */     cmp     %i4,1       ! n < 1 ?
/* 0x0030        */     bl,pn   %icc,.L77000075 ! if yes, branch to end of main()
/* 0x0034     41 */     mov     %o0,%i2     ! %i2 (result) = %o0 ( result of fibonacci() )

!   43        !    printf("Fibonacci (%d) is %u\n", i, *result++);

            .L77000082:
/* 0x0038     42 */     mov     1,%i3       ! i = 1

            .L900000207:
                            ! beginning of loop body
/* 0x003c     43 */     ld      [%i2],%o2       ! %o2 (3rd arg) = value at &result
/* 0x0040        */     add     %i1,36,%o0      ! %o0 (1st arg) = %i1+36 (&.L40)
/* 0x0044        */     add     %i2,4,%i2       ! increment &result by 4, result now points to the
                            ! next value in fib_array[]
/* 0x0048        */     call    printf  ! params =  %o0 %o1 %o2 ! Result =
/* 0x004c        */     mov     %i3,%o1     ! %o1 (2nd arg) = %i3 (i)
/* 0x0050        */     ld      [%fp-4],%i0     ! %i0 = value at %fp-4 (n)
/* 0x0054     42 */     add     %i3,1,%i3       ! increment i by 1
/* 0x0058        */     cmp     %i3,%i0     ! i <= n ?
/* 0x005c        */     ble,pt  %icc,.L900000207! if yes, goto beginning of loop body
/* 0x0060        */     nop             ! end of the loop body

            .L77000075:
/* 0x0064     42 */     ret
/* 0x0068        */     restore %g0,0,%o0
/* 0x006c      0 */     .type   main,#function
/* 0x006c      0 */     .size   main,(.-main)