The "no-system" code, defined in crt0.s, starts from _start at address 0x00000000. It sets the stack pointer, global pointer, and exception trap registers, and then jumps to __start_2.
This code makes the following calls:
void __start_2 (void) { _zero_bss (&__bss_start, 0, &_end - &__bss_start); _init (); exit (main (0, 0, 0)); }
See zero_bss.
Note from the symbol table that __bss_start equals _end, so that the bss section has zero length.
# # crt0.s # # NIOS2 startup code # # Startup code # This will work with the simulator, which is # its real purpose. .section .text .align 3 .globl _start .type _start,@function _start: # set up the stack pointer. movhi sp, %hiadj(nasys_stack_top) addi sp, sp, %lo(nasys_stack_top) # make sure it is aligned nor sp, sp, sp ori sp, sp, 0x7 # clear lowest three bits nor sp, sp, sp # set up the global pointer. movhi gp, %hiadj(_gp) addi gp, gp, %lo(_gp) #set up the exception temporary movhi et, %hiadj(_end) addi et, et, %lo(_end) movhi r2, %hiadj(__start_2) addi r2, r2, %lo(__start_2) jmp r2
0000080c A __bss_start 0000080c A _edata 0000080c A _end 00008800 A _gp 00000808 G _impure_ptr 00000288 W _init 00000000 T _start 000002cc T _zero_bss 0000048c d impure_data 07ffff00 A nasys_stack_top
See key for the meaning of the symbol type characters.
00000000 <_start>: 0: 06c20034 movhi sp,2048 4: deffc004 addi sp,sp,-256 8: def6303a nor sp,sp,sp c: dec001d4 ori sp,sp,7 10: def6303a nor sp,sp,sp 14: 06800074 movhi gp,1 18: d6a20004 addi gp,gp,-30720 1c: 06000034 movhi et,0 20: c6020304 addi et,et,2060 24: 00800034 movhi r2,0 28: 1080a304 addi r2,r2,652 2c: 1000683a jmp r2
sp | nasys_stack_top | 0x7ffff00 |
---|---|---|
gp | _gp | 0x8800 |
et | _end | 0x80c |
0x00000000 <_start>: 0x06c20034 movhi sp, 2048 [dstData=0x8000000 dstReg=sp] 0x00000004 <_start+0x4>: 0xdeffc004 addi sp, sp, -256 [dstData=0x7ffff00 dstReg=sp] 0x00000008 <_start+0x8>: 0xdef6303a nor sp, sp, sp [dstData=0xf80000ff dstReg=sp] 0x0000000c <_start+0xc>: 0xdec001d4 ori sp, sp, 7 [dstData=0xf80000ff dstReg=sp] 0x00000010 <_start+0x10>: 0xdef6303a nor sp, sp, sp [dstData=0x7ffff00 dstReg=sp] 0x00000014 <_start+0x14>: 0x06800074 movhi gp, 1 [dstData=0x10000 dstReg=gp] 0x00000018 <_start+0x18>: 0xd6a20004 addi gp, gp, -30720 [dstData=0x8800 dstReg=gp] 0x0000001c <_start+0x1c>: 0x06000034 movhi et, 0 [dstData=0x0 dstReg=et] 0x00000020 <_start+0x20>: 0xc6020304 addi et, et, 2060 [dstData=0x80c dstReg=et] 0x00000024 <_start+0x24>: 0x00800034 movhi r2, 0 [dstData=0x0 dstReg=r2] 0x00000028 <_start+0x28>: 0x1080a304 addi r2, r2, 652 [dstData=0x28c dstReg=r2] 0x0000002c <_start+0x2c>: 0x1000683a jmp r2 [targetPcb=0x28c]
extern void __bss_start; extern void _end; extern int main (int, char **, char **); void __fake_init () { /* Do nothing */ } void _init () __attribute__ ((weak, alias ("__fake_init"))); void __start_2 (void) { _zero_bss (&__bss_start, 0, &_end - &__bss_start); _init (); exit (main (0, 0, 0)); }
00000288 <__fake_init>: 288: f800283a ret 0000028c <__start_2>: 28c: 01000034 movhi r4,0 290: 21020304 addi r4,r4,2060 294: 01800034 movhi r6,0 298: 31820304 addi r6,r6,2060 29c: deffff04 addi sp,sp,-4 2a0: 310dc83a sub r6,r6,r4 2a4: 000b883a mov r5,zero 2a8: dfc00015 stw ra,0(sp) 2ac: 00002cc0 call 2cc <_zero_bss> 2b0: 00002880 call 288 <__fake_init> 2b4: 0009883a mov r4,zero 2b8: 000b883a mov r5,zero 2bc: 000d883a mov r6,zero 2c0: 00000300 call 30 <main> 2c4: 1009883a mov r4,r2 2c8: 00002d80 call 2d8 <exit>
The simulation extends to the call to main.
0x00000000 <_start>: 0x06c20034 movhi sp, 2048 [dstData=0x8000000 dstReg=sp] 0x00000004 <_start+0x4>: 0xdeffc004 addi sp, sp, -256 [dstData=0x7ffff00 dstReg=sp] 0x00000008 <_start+0x8>: 0xdef6303a nor sp, sp, sp [dstData=0xf80000ff dstReg=sp] 0x0000000c <_start+0xc>: 0xdec001d4 ori sp, sp, 7 [dstData=0xf80000ff dstReg=sp] 0x00000010 <_start+0x10>: 0xdef6303a nor sp, sp, sp [dstData=0x7ffff00 dstReg=sp] 0x00000014 <_start+0x14>: 0x06800074 movhi gp, 1 [dstData=0x10000 dstReg=gp] 0x00000018 <_start+0x18>: 0xd6a20004 addi gp, gp, -30720 [dstData=0x8800 dstReg=gp] 0x0000001c <_start+0x1c>: 0x06000034 movhi et, 0 [dstData=0x0 dstReg=et] 0x00000020 <_start+0x20>: 0xc6020304 addi et, et, 2060 [dstData=0x80c dstReg=et] 0x00000024 <_start+0x24>: 0x00800034 movhi r2, 0 [dstData=0x0 dstReg=r2] 0x00000028 <_start+0x28>: 0x1080a304 addi r2, r2, 652 [dstData=0x28c dstReg=r2] 0x0000002c <_start+0x2c>: 0x1000683a jmp r2 [targetPcb=0x28c] 0x0000028c <__start_2>: 0x01000034 movhi r4, 0 [dstData=0x0 dstReg=r4] 0x00000290 <__start_2+0x4>: 0x21020304 addi r4, r4, 2060 [dstData=0x80c dstReg=r4] 0x00000294 <__start_2+0x8>: 0x01800034 movhi r6, 0 [dstData=0x0 dstReg=r6] 0x00000298 <__start_2+0xc>: 0x31820304 addi r6, r6, 2060 [dstData=0x80c dstReg=r6] 0x0000029c <__start_2+0x10>: 0xdeffff04 addi sp, sp, -4 [dstData=0x7fffefc dstReg=sp] 0x000002a0 <__start_2+0x14>: 0x310dc83a sub r6, r6, r4 [dstData=0x0 dstReg=r6] 0x000002a4 <__start_2+0x18>: 0x000b883a mov r5, r0 [dstData=0x0 dstReg=r5] 0x000002a8 <__start_2+0x1c>: 0xdfc00015 stw ra, 0(sp) [memAddr=0x7fffefc stData=0xdeadbeef] 0x000002ac <__start_2+0x20>: 0x00002cc0 call 0x2cc <_zero_bss> [dstData=0x2b0 dstReg=ra]
Execution of _zero_bss and memset takes place here.
0x000002b0 <__start_2+0x24>: 0x00002880 call 0x288 <__fake_init> [dstData=0x2b4 dstReg=ra] 0x00000288 <__fake_init>: 0xf800283a ret [targetPcb=0x2b4] 0x000002b4 <__start_2+0x28>: 0x0009883a mov r4, r0 [dstData=0x0 dstReg=r4] 0x000002b8 <__start_2+0x2c>: 0x000b883a mov r5, r0 [dstData=0x0 dstReg=r5] 0x000002bc <__start_2+0x30>: 0x000d883a mov r6, r0 [dstData=0x0 dstReg=r6] 0x000002c0 <__start_2+0x34>: 0x00000300 call 0x30 <main> [dstData=0x2c4 dstReg=ra]
_zero_bss just calls memset. In this example, there are no bytes to set since the bss section has zero length.
#include "config.h" #include <string.h> void _zero_bss (void *base, int c, size_t count) { memset (base, c, count); }
000002cc <_zero_bss>: 2cc: 02000034 movhi r8,0 2d0: 4200ef04 addi r8,r8,956 2d4: 4000683a jmp r8
0x000002cc <_zero_bss>: 0x02000034 movhi r8, 0 [dstData=0x0 dstReg=r8] 0x000002d0 <_zero_bss+0x4>: 0x4200ef04 addi r8, r8, 956 [dstData=0x3bc dstReg=r8] 0x000002d4 <_zero_bss+0x8>: 0x4000683a jmp r8 [targetPcb=0x3bc]
/* FUNCTION <<memset>>---set an area of memory INDEX memset ANSI_SYNOPSIS #include <string.h> void *memset(const void *<[dst]>, int <[c]>, size_t <[length]>); TRAD_SYNOPSIS #include <string.h> void *memset(<[dst]>, <[c]>, <[length]>) void *<[dst]>; int <[c]>; size_t <[length]>; DESCRIPTION This function converts the argument <[c]> into an unsigned char and fills the first <[length]> characters of the array pointed to by <[dst]> to the value. RETURNS <<memset>> returns the value of <[m]>. PORTABILITY <<memset>> is ANSI C. <<memset>> requires no supporting OS subroutines. QUICKREF memset ansi pure */ #include <string.h> #define LBLOCKSIZE (sizeof(long)) #define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1)) #define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE) _PTR _DEFUN (memset, (m, c, n), _PTR m _AND int c _AND size_t n) { #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) char *s = (char *) m; while (n-- != 0) { *s++ = (char) c; } return m; #else char *s = (char *) m; int i; unsigned long buffer; unsigned long *aligned_addr; unsigned int d = c & 0xff; /* To avoid sign extension, copy C to an unsigned variable. */ if (!TOO_SMALL (n) && !UNALIGNED (m)) { /* If we get this far, we know that n is large and m is word-aligned. */ aligned_addr = (unsigned long*)m; /* Store D into each char sized location in BUFFER so that we can set large blocks quickly. */ if (LBLOCKSIZE == 4) { buffer = (d << 8) | d; buffer |= (buffer << 16); } else { buffer = 0; for (i = 0; i < LBLOCKSIZE; i++) buffer = (buffer << 8) | d; } while (n >= LBLOCKSIZE*4) { *aligned_addr++ = buffer; *aligned_addr++ = buffer; *aligned_addr++ = buffer; *aligned_addr++ = buffer; n -= 4*LBLOCKSIZE; } while (n >= LBLOCKSIZE) { *aligned_addr++ = buffer; n -= LBLOCKSIZE; } /* Pick up the remainder with a bytewise loop. */ s = (char*)aligned_addr; } while (n--) { *s++ = (char)d; } return m; #endif /* not PREFER_SIZE_OVER_SPEED */ }
000003bc <memset>: 3bc: 008000c4 movi r2,3 3c0: 29403fcc andi r5,r5,255 3c4: 2007883a mov r3,r4 3c8: 11801a2e bgeu r2,r6,434 <memset+0x78> 3cc: 2084703a and r2,r4,r2 3d0: 1000181e bne r2,zero,434 <memset+0x78> 3d4: 2806923a slli r3,r5,8 3d8: 200f883a mov r7,r4 3dc: 1946b03a or r3,r3,r5 3e0: 1804943a slli r2,r3,16 3e4: 1886b03a or r3,r3,r2 3e8: 008003c4 movi r2,15 3ec: 11800a2e bgeu r2,r6,418 <memset+0x5c> 3f0: 38c00015 stw r3,0(r7) 3f4: 39c00104 addi r7,r7,4 3f8: 38c00015 stw r3,0(r7) 3fc: 39c00104 addi r7,r7,4 400: 38c00015 stw r3,0(r7) 404: 39c00104 addi r7,r7,4 408: 38c00015 stw r3,0(r7) 40c: 31bffc04 addi r6,r6,-16 410: 39c00104 addi r7,r7,4 414: 11bff636 bltu r2,r6,3f0 <memset+0x34> 418: 008000c4 movi r2,3 41c: 1180042e bgeu r2,r6,430 <memset+0x74> 420: 38c00015 stw r3,0(r7) 424: 31bfff04 addi r6,r6,-4 428: 39c00104 addi r7,r7,4 42c: 11bffc36 bltu r2,r6,420 <memset+0x64> 430: 3807883a mov r3,r7 434: 31bfffc4 addi r6,r6,-1 438: 00bfffc4 movi r2,-1 43c: 30800426 beq r6,r2,450 <memset+0x94> 440: 19400005 stb r5,0(r3) 444: 31bfffc4 addi r6,r6,-1 448: 18c00044 addi r3,r3,1 44c: 30bffc1e bne r6,r2,440 <memset+0x84> 450: 2005883a mov r2,r4 454: f800283a ret
In this example, memset is copying zero bytes, so execution is brief.
0x000003bc <memset>: 0x008000c4 movi r2, 3 [dstData=0x3 dstReg=r2] 0x000003c0 <memset+0x4>: 0x29403fcc andi r5, r5, 255 [dstData=0x0 dstReg=r5] 0x000003c4 <memset+0x8>: 0x2007883a mov r3, r4 [dstData=0x80c dstReg=r3] 0x000003c8 <memset+0xc>: 0x11801a2e bgeu r2, r6, 0x434 <memset+0x78> [passed] 0x00000434 <memset+0x78>: 0x31bfffc4 addi r6, r6, -1 [dstData=0xffffffff dstReg=r6] 0x00000438 <memset+0x7c>: 0x00bfffc4 movi r2, -1 [dstData=0xffffffff dstReg=r2] 0x0000043c <memset+0x80>: 0x30800426 beq r6, r2, 0x450 <memset+0x94> [passed] 0x00000450 <memset+0x94>: 0x2005883a mov r2, r4 [dstData=0x80c dstReg=r2] 0x00000454 <memset+0x98>: 0xf800283a ret [targetPcb=0x2b0]
Maintained by John Loomis, last updated 5 April 2007