Skip Navigation Links | |
Exit Print View | |
SPARC Assembly Language Reference Manual Oracle Solaris 11.1 Information Library |
2. Executable and Linking Format
3. Directives and Pseudo-Operations
6. Writing Functions -- The SPARC ABI
7. Assembler Inline Functions and __asm Code
A. Using the Assembler Command Line
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)