The following code takes a sample C language program and generates the corresponding assembly code using the Oracle Developer Studio C compiler running on the Oracle 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 5 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 Developer 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 6 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)