MIPS架构之start.s汇编分析

来源:互联网 发布:奥迪矩阵式led大灯 编辑:程序博客网 时间:2024/06/07 16:55

一、mips架构通用寄存器命名




二、mips汇编指令操作

1、指令集



2、实例:

#example .data array1: .space 12         #  declare 12 bytes of storage                                   # to hold array of 3 integers  .text __start:  la  $t0, array1              #  load base address of array                                     # into register $t0  li  $t1, 5              #  $t1 = 5   ("load immediate")sw  $t1, ($t0)              #  first array element set to 5                            # indirect addressing  li  $t1, 13                #   $t1 = 13 sw  $t1, 4($t0)           # second array element set to 13  li $t1, -7                 #   $t1 = -7  sw  $t1, 8($t0)            # third array element set to -7

start.s汇编分析

    mtc0 zero, CP0_WATCHLO    mtc0 zero, CP0_WATCHHI                清除硬件数据断点,防止产生调试断点,导致程序停止。                                      芯片在复位后,某些寄存器的内容也许是你想要的结果,但是谁知道呢,为了保证准确无误,最好还是重新进行手动初始化    mfc0 k0, CP0_STATUS    li  k1, ~ST0_IE    and k0, k1    mtc0 k0, CP0_STATUS                    禁止全局中断
    mtc0 zero, CP0_CAUSE                  初始化异常寄存器,清除异常原因指示    mtc0 zero, CP0_COUNT    mtc0 zero, CP0_COMPARE                                  初始化时钟寄存器,防止产生计数器中断    li t0, CONF_CM_UNCACHED    mtc0 t0, CP0_CONFIG                                 设置kseg0区不经过cache。cache需要先初始化才能使用。    bal 1f    nop    .word _gp1:    lw gp, 0(ra)                                  bal分支调用,ra返回地址指向下下一条指令,即.word _gp                                 把.word _gp的存储位置载入gp寄存器,即设置GOT表的起始位置    la t9, lowlevel_init    jalr t9    nop                               根据CPU rate初始化外部时钟、内存。                                 lowlevel_init函数定义见lowlevel_init.S    la t9, mips_cache_reset    jalr t9     nop                                初始化高速缓存cache。                                 mips_cache_reset函数定义见cache.S    li t0, CONF_CM_CACHABLE_NONCOHERENT    mtc0 t0, CP0_CONFIG                              设置kseg0区经过cache    li a0, CFG_INIT_SP_OFFSET    la t9, mips_cache_lock    jalr t9    nop    li t0, CFG_SDRAM_BASE +     CFG_INIT_SP_OFFSET    la sp, 0(t0)                           C语言程序(接下来的函数board_init_f)调用需要栈,而ram还没有初始化不能使用,所以用CACHE_LOCK_SIZE大小的L1 Dcache锁定作为临时栈使用                          以sp开始,CACHE_LOCK_SIZE大小的堆栈,使用                          D-cache临时替代    la t9, board_init_f   初始化    j t9    nop                          board_init_f函数定义见boardrelocate_code:                 对应board.c里的relocate_code (addr_sp, id, addr),此时a0=addr_sp,a1=id,a3=addr。    move sp, a0                设置新的sp = addr_sp    li t0, CFG_MONITOR_BASE      board/xxx/config.mk #define CFG_MONITOR_BASE TEXT_BASE

    la t3, in_ram                  t0 = uboot程序在flash的超始地址,t1 =  准备把uboot程序移到ram中的起始地址    lw t2, -12(t3)                t2 = uboot程序的结束地址            move t1, a2                               move t6, gp    sub gp, CFG_MONITOR_BASE     计算旧的gp与相对于TEXT_BASE的偏移       add gp, a2                    计算新的gp在移动目的地内存中的地址    sub t6, gp, t6                t6 = 新gp(内存中)与旧gp(flash中)的地址偏移量,这个值也是整个uboot从flash移到内存的偏移量。等同于(Destination Address - CFG_MONITOR_BASE)1:    lw t3, 0(t0)    sw t3, 0(t1)    addu t0, 4    ble t0, t2, 1b    addu t1, 4                                按字拷贝,把uboot bin的内容从源地址(flash)拷贝到目的地址(内存),拷贝的长度是从uboot开始到uboot_end_data为止,uboot_end_data后面是bss段,详见uboot.lds    addi t0, a2, in_ram - _start    j t0    nop                               计算in_ram在内存中的新地址保存到t0,然后跳转到内存中运行in_ram。从此开始,uboot的代码将在ram中运行了    .gpword_GLOBAL_OFFSET_TABLE    .word uboot_end_data    .word uboot_end    .word num_got_entriesin_ram:    t3 = num_got_entries,t4 = 新的GOT[2]    li t2, 21:    lw t1, 0(t4)    beqz t1, 2f    add t1, t6    sw t1, 0(t4)2:    addi t2, 1    blt t2, t3, 1b    addi t4, 4                    这里是一个循环,从GOT[2]开始,判断如果GOT表项有内容,则把内容从旧的GOT表拷贝到新的GOT表里。为什么要做拷贝呢?上面的程序已经把uboot整个程序从                    flash拷贝到了ram里,注意,只是内容拷贝,GOT里的地址还是老地址,所以要做重定位(如果是静态编译且属于模块内相对偏移,就不需要这个步骤了)。手工重定位                    的方法就是把旧GOT里的内容读取,然后加上偏移(uboot在flash与ram的偏移)赋值给新GOT里的对应表项                   程序构建过程(编译和生成程序时的链接)为每个链接单元(构成动态链接程序的二进制文件,如.o、.a、.so)至少定义一个GOT,每个函数都可以找到自己的GOT,因为                   GOT的位置离链接单元的入口点的偏移量是固定已知的。链接单元作为一个整体载入内存,所以GOT的内部偏移量与编译时是一样的。                   u-boot在编译时使用-fpic,会生成一个.got段来存储绝对地址符号。    lw t1, -12(t0)    lw t2, -8(t0)    add t1, t6    add t2, t6    sub t1, 41:    addi t1, 4    bltl t1, t2, 1b    sw zero, 0(t1)    t1 = uboot_end_data,      t2 = uboot_end                                 进行BSS段的清零,此时还没有操作系统,动态链接器,加载器等这些东东都还没有,所以要手动执行清零    move a0, a1    la t9, board_init_r    j t9    move a1, a2                        跳转到ram中的board_init_r执行,根据MIPS ABI规范,a0、a1分别是board_init_r的第一个、第二个参数,即board_init_r (gd_t *id, ulong dest_addr)中id = a0,                        dest_addr = a2



0 0
原创粉丝点击