tinyriscv启动代码分析

首先,展示RISC-V代码段数据段的内存分布示意图。在这里插入图片描述

下面是tinyriscv项目sdk文件路径下的启动代码。

    .section .init;
    .globl _start;
    .type _start,@function


_start:
.option push
.option norelax
    la gp, __global_pointer$
.option pop
    la sp, _sp
#ifdef SIMULATION
    /* clear sim result flags */
    csrrwi x0, sstatus, 0x0
#endif

    /* Load data section */
    la a0, _data_lma
    la a1, _data
    la a2, _edata
    bgeu a1, a2, 2f
1:
    lw t0, (a0)
    sw t0, (a1)
    addi a0, a0, 4
    addi a1, a1, 4
    bltu a1, a2, 1b
2:

    /* Clear bss section */
    la a0, __bss_start
    la a1, _end
    bgeu a0, a1, 2f
1:
    sw zero, (a0)
    addi a0, a0, 4
    bltu a0, a1, 1b
2:

    /* set exception and interrupt entry */
    la a0, trap_entry
    csrw mtvec, a0

    li a0, 0
    li a1, 0
    call main

loop:
    j loop

以一个period打头的命令是assembler directives,他们是对汇编器的命令,而不是汇编器需要翻译的命令。他们告诉assembler把data和text放到哪。Figure 3.9是RISC-V assembler的directives。
Common RISC-V assembler directives
.section .init;Subsequent items are stored in the section named .init.
globl _start;:Declare that label sym is global and may be referenced from other files.
这里的.option push, .option pop, option norelax,在上面的表格都有相应的描述。
这里为什么需要使用norelax?
笔者尝试去掉norelax的选项,然后进行反汇编分析。发现去掉会导致结果异常,gp寄存器不能正确指向__global_pointer。汇编器出于自己的喜好,做了一些骚操作,导致结果不符合预期。编译器这样做的原因已经超出了笔者的认知范围,笔者暂时无法回答。但从反汇编结果来看,加上准没错。

反汇编文件在tinyriscv/sdk/examples/freertos/Demo/tinyriscv_GCC路径下的freertos.dump。笔者在这里贴上_start函数的反汇编,帮助分析启动代码。

 Disassembly of section .init:

 00000000 <_start>:
    0:   20001197            auipc   gp,0x20001
    4:   91018193            addi    gp,gp,-1776 # 20000910 <__global_pointer$>
    8:   20004117            auipc   sp,0x20004
    c:   ff810113            addi    sp,sp,-8 # 20004000 <__freertos_irq_stack_top>
   10:   00002517            auipc   a0,0x2
   14:   29850513            addi    a0,a0,664 # 22a8 <_data_lma>
   18:   20000597            auipc   a1,0x20000
   1c:   fe858593            addi    a1,a1,-24 # 20000000 <_data>
   20:   20000617            auipc   a2,0x20000
   24:   0f460613            addi    a2,a2,244 # 20000114 <xQueue>
   28:   00c5fc63            bgeu    a1,a2,40 <_start+0x40>
   2c:   00052283            lw  t0,0(a0)
   30:   0055a023            sw  t0,0(a1)
   34:   00450513            addi    a0,a0,4
   38:   00458593            addi    a1,a1,4
   3c:   fec5e8e3            bltu    a1,a2,2c <_start+0x2c>
   40:   20000517            auipc   a0,0x20000
   44:   0d450513            addi    a0,a0,212 # 20000114 <xQueue>
   48:   14018593            addi    a1,gp,320 # 20000a50 <_end>
   4c:   00b57863            bgeu    a0,a1,5c <_start+0x5c>
   50:   00052023            sw  zero,0(a0)
   54:   00450513            addi    a0,a0,4
   58:   feb56ce3            bltu    a0,a1,50 <_start+0x50>
   5c:   00000517            auipc   a0,0x0
   60:   63050513            addi    a0,a0,1584 # 68c <trap_entry>
   64:   30551073            csrw    mtvec,a0
   68:   00000513            li  a0,0
   6c:   00000593            li  a1,0
   70:   090000ef            jal ra,100 <main>

启动代码做了下面几件事:

  1. 初始化gp:gp寄存器存__global_pointer的内存地址
  2. 初始化sp:sp寄存器存_sp的内存地址
  3. 初始化data段
  4. 初始化bss段,清零
  5. 初始化中断向量,将trap_entry符号所在的地址给到mtvec寄存器。
  6. 跳转到main
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值