完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
1. 设置CPU模式
1.1. globl #include #include /* ************************************************************************* * * Jump vector table as in table 3.1 in [1] * ************************************************************************* */ .globl _start globl是个关键字,对应含义为: 意思很简单,就是相当于C语言中的Extern,声明此变量。 u-boot.lds文件里有: ENTRY(_start) 即指定入口为_start,而由下面的_start的含义可以得知,_start就是整个start.S的最开始,即整个uboot的代码的开始。 1.2. _start _start : b reset _start后面加上一个冒号’:’,表示其是一个标号Label,类似于C语言goto后面的标号。而同时,_start的值,也就是这个代码的位置了,此处即为代码的最开始,相对的0的位置。而此处最开始的相对的0位置,在程序开始运行的时候,如果是从NorFlash启动,那么其地址是0, _stat=0 如果是重新relocate代码之后,就是我们定义的值了,即,在config.mk中的: TEXT_BASE = 0x33D00000 表示是代码段的基地址,即 _start=TEXT_BASE=0x33D00000 而_start标号后面的: b reset 就是跳转到对应的标号为reset的位置。 1.3. ldr ldr pc, _undefined_instruction ldr pc, _software_interrupt ldr pc, _prefetch_abort ldr pc, _data_abort ldr pc, _not_used ldr pc, _irq ldr pc, _fiq ldr命令的语法为: LDR{条件} 目的寄存器,<存储器地址> LDR指令用于从存储器中将一个32位的字数据传送到目的寄存器中。该指令通常用于从存储器中读取32位的字数据到通用寄存器,然后对数据进行处理。当程序计数器PC作为目的寄存器时,指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转。该指令在程序设计中比较常用,且寻址方式灵活多样,请读者认真掌握。 指令示例: LDR R0,[R1] ;将存储器地址为R1的字数据读入寄存器R0。 LDR R0,[R1,R2] ;将存储器地址为R1+R2的字数据读入寄存器R0。 LDR R0,[R1,#8] ;将存储器地址为R1+8的字数据读入寄存器R0。 LDR R0,[R1,R2]! ;将存储器地址为R1+R2的字数据读入寄存器R0,并将新地址R1+R2写入R1。 LDR R0,[R1,#8]! ;将存储器地址为R1+8的字数据读入寄存器R0,并将新地址R1+8写入R1。 LDR R0,[R1],R2 ;将存储器地址为R1的字数据读入寄存器R0,并将新地址R1+R2写入R1。 LDR R0,[R1,R2,LSL#2]! ;将存储器地址为R1+R2×4的字数据读入寄存器R0,并将新地址R1+R2×4写入R1 LDRR0,[R1],R2,LSL#2 ;将存储器地址为R1的字数据读入寄存器R0,并将新地址R1+R2×4写入R1。 ARM是RISC结构,数据从内存到CPU之间的移动只能通过L/S指令来完成,也就是ldr/str指令。 比如想把数据从内存中某处读取到寄存器中,只能使用ldr 比如: ldr r0, 0x12345678 就是把0x12345678这个地址中的值存放到r0中。 上面那些ldr的作用,以第一个_undefined_instruction为例,就是将地址为_undefined_instruction中的一个word的值,赋值给pc。 1.4. .word _undefined_instruction: .word undefined_instruction _software_interrupt: .word software_interrupt _prefetch_abort: .word prefetch_abort _data_abort: .word data_abort _not_used: .word not_used _irq: .word irq _fiq: .word fiq word .word expr {,expr}… 分配一段字内存单元,并用expr初始化字内存单元(32bit) 所以上面的含义,以_undefined_instruction为例,就是,此处分配了一个word=32bit=4字节的地址空间,里面存放的值是undefined_instruction。 而此处_undefined_instruction也就是该地址空间的地址了。用C语言来表达就是: _undefined_instruction = &undefined_instruction 或 *_undefined_instruction = undefined_instruction 在后面的代码,我们可以看到,undefined_instruction也是一个标号,即一个地址值,对应着就是在发生“未定义指令”的时候,系统所要去执行的代码。 (其他几个对应的“软件中断”,“预取指错误”,“数据错误”,“未定义”,“(普通)中断”,“快速中断”,也是同样的做法,跳转到对应的位置执行对应的代码。) 所以: ldr pc, 标号1 ...... 标号1:.word 标号2 ...... 标号2: ......(具体要执行的代码) 的意思就是,将地址为标号1中内容载入到pc,而地址为标号1中的内容,正好装的是标号2。 用C语言表达其实很简单: PC = *(标号1) = 标号2 对PC赋值,即是实现代码跳转,所以整个这段汇编代码的意思就是: 跳转到标号2的位置,执行对应的代码。 1.5. .balignl .balignl 16,0xdeadbeef balignl这个标号的语法及含义: 所以意思就是,接下来的代码,都要16字节对齐,不足之处,用0xdeadbeef填充。此处0xdeadbeef本身没有真正的意义,但是很明显,字面上的意思是,(坏)死的牛肉。 虽然其本身没有实际意义,但是其是在十六进制下,能表示出来的,为数不多的,可读的单词之一了。 另外一个相对常见的是:0xbadc0de,意思是bad code,坏的代码,注意其中的o是0,因为十六进制中是没有o的。 这些“单词”,相对的作用是,使得读代码的人,以及在查看程序运行结果时,容易看懂,便于引起注意。 1.6. _TEXT_BASE _armboot_start /* ************************************************************************* * * Startup Code (called from the ARM reset exception vector) * * do important init only if we don't start from memory! * relocate armboot to ram * setup stack * jump to second stage * ************************************************************************* */ _TEXT_BASE: .word TEXT_BASE .globl _armboot_start _armboot_start: .word _start _TEXT_BASE是一个标号地址,此地址中是一个word类型的变量,变量名是TEXT_BASE,此值见名知意,是text的base,即代码的基地址,可以在config.mk中找到其定义: TEXT_BASE = 0x33D00000 .globl _armboot_start此含义可用C语言表示为: *(_armboot_start) = _start 1.7. _bss_start _bss_end /* * These are defined in the board-specific linker script. */ .globl _bss_start _bss_start: .word __bss_start .globl _bss_end _bss_end: .word _end 关于_bss_start和_bss_end都只是两个标号,对应着此处的地址。 而两个地址里面分别存放的值是__bss_start和_end,这两个的值,根据注释所说,是定义在开发板相关的链接脚本里面的,我们此处的开发板相关的链接脚本是: u-boot.lds 其中可以找到__bss_start和_end的定义: __bss_start = .; .bss : { *(.bss) } _end = .; 而关于_bss_start和_bss_end定义为.glogl即全局变量,是因为uboot的其他源码中要用到这两个变量,详情请自己去搜索源码。 1.8. IRQ_STACK_START FIQ_STACK_START #ifdef CONFIG_USE_IRQ /* IRQ stack memory (calculated at run-time) */ .globl IRQ_STACK_START IRQ_STACK_START: .word 0x0badc0de /* IRQ stack memory (calculated at run-time) */ .globl FIQ_STACK_START FIQ_STACK_START: .word 0x0badc0de #endif 同上,IRQ_STACK_START和FIQ_STACK_START,也是在cpu_init中用到了。 不过此处,是只有当定义了宏CONFIG_USE_IRQ的时候,才用到这两个变量,其含义也很明显,只有用到了中断IRQ,才会用到中断的堆栈,才有中端堆栈的起始地址。 快速中断FIQ,同理。 1.9 几个汇编指令 reset: mrs r0, cpsr bic r0, r0, #0x1f orr r0, r0, #0xd3 msr cpsr,r0 CPSR 是当前的程序状态寄存器(Current Program Status Register),而 SPSR 是保存的程序状态寄存器(Saved Program Status Register)。 1.9.1 MRS指令 MRS指令的格式为: MRS{条件} 通用寄存器,程序状态寄存器(CPSR或SPSR) MRS指令用于将程序状态寄存器的内容传送到通用寄存器中。该指令一般用在以下两种情况: 当需要改变程序状态寄存器的内容时,可用MRS将程序状态寄存器的内容读入通用寄存器,修改后再写回程序状态寄存器。 当在异常处理或进程切换时,需要保存程序状态寄存器的值,可先用该指令读出程序状态寄存器的值,然后保存。 指令示例: MRS R0,CPSR ;传送CPSR的内容到R0 MRS R0,SPSR ;传送SPSR的内容到R0” 所以,上述汇编代码含义为,将CPSR的值赋给R0寄存器。 1.9.2 bic指令 BIC指令的格式为: BIC{条件}{S} 目的寄存器,操作数1,操作数2 BIC指令用于清除操作数1的某些位,并把结果放置到目的寄存器中。操作数1应是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。操作数2为32位的掩码,如果在掩码中设置了某一位,则清除这一位。未设置的掩码位保持不变。 而0x1f=11111b 所以,此行代码的含义就是,清除r0的bit[4:0]位。 1.9.3 ORR指令 ORR指令的格式为: ORR{条件}{S} 目的寄存器,操作数1,操作数2 ORR指令用于在两个操作数上进行逻辑或运算,并把结果放置到目的寄存器中。 操作数1应是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。该指令常用于设置操作数1的某些位。 指令示例: ORR R0,R0,#3 ; 该指令设置R0的0、1位,其余位保持不变。 所以此行汇编代码的含义为:而0xd3=1101 0011, 将r0与0xd3算数或运算,然后将结果给r0,即把r0的bit[7:6]和bit[4]和bit[1:0]置为1。 1.9.4 MSR指令 MSR指令的格式为: MSR{条件} 程序状态寄存器(CPSR或SPSR)_<域>,操作数 MSR指令用于将操作数的内容传送到程序状态寄存器的特定域中。其中,操作数可以为通用寄存器或立即数。<域>用于设置程序状态寄存器中需要操作的位,32位的程序状态寄存器可分为4个域: 位[31:24]为条件标志位域,用f表示; 位[23:16]为状态位域,用s表示; 位[15:8]为扩展位域,用x表示; 位[7:0]为控制位域,用c表示; 该指令通常用于恢复或改变程序状态寄存器的内容,在使用时,一般要在MSR指令中指明将要操作的域。 指令示例: MSR CPSR,R0 ;传送R0的内容到CPSR MSR SPSR,R0 ;传送R0的内容到SPSR MSR CPSR_c,R0 ;传送R0的内容到SPSR,但仅仅修改CPSR中的控制位域 此行汇编代码含义为,将r0的值赋给CPSR。 所以,上面四行汇编代码的含义就很清楚了。先是把CPSR的值放到r0寄存器中,然后清除bit[4:0],然后再或上0xd3=1101 0011b。 原作者:口袋里のInit |
|
相关推荐 |
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
迅为RK3568开发板EMMC镜像导出打包update.img
403 浏览 0 评论
飞凌嵌入式-ELFBOARD 硬件知识分享-ELF 2电源电路讲解
1004 浏览 0 评论
1713 浏览 0 评论
飞凌嵌入式ElfBoard ELF 1板卡-mfgtools烧录流程介绍之烧写所需镜像
1511 浏览 0 评论
飞凌嵌入式ElfBoard ELF 1板卡-mfgtools烧录流程之烧写方法
956 浏览 0 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-26 12:29 , Processed in 0.501016 second(s), Total 38, Slave 33 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号