ARM-启动代码start.S

伪操作

  • 汇编程序中以 . 开头的名称并不是指令的助记符,不会被翻译成机器指令,而是给汇编器一些特殊指示,称为汇编指示(Assembler Directive)或伪操作(Pseudo-operation),由于它不是真正的指令所以加个“伪”字。
    1) .section指示把代码划分成若干个段(Section),程序被操作系统加载执行时,每个段被加载到不同的地址,操作系统对不同的页面设置不同的读、写、执行权限。
    2).data段保存程序的数据,是可读可写的,相当于C程序的全局变量。本程序中没有定义数据,所以.data段是空的。

  • .section / .text
    .text段保存代码,是只读和可执行的,表示后面那些指令都属于.text段。

  • .globl _start
    (1)_start是一个符号(Symbol),符号:在汇编程序中表示一个地址。汇编程序经过汇编器的编译后,所有符号都会被替换成它之前所代表的地址值。
    (2)在C语言中,我们通过变量名访问一个变量,其实就是读写操作对应地址上的内存空间,我们通过函数名调用一个函数,其实就是跳转到该函数第一条指令所在的地址(函数名即首地址),所以变量名和函数名都是符号,本质上都是代表内存空间的地址。
    (3).globl是告诉汇编器,_start这个符号要被链接器链接到,所以要在目标文件的符号表中标记它是一个全局符号。_start就像C程序的main主函数一样特殊,是整个程序的入口。链接器在链接时会查找目标文件中的_start符号代表的地址,把它设置为整个程序的入口地址,因此每个汇编程序都要提供一个_start符号并且用.globl声明。如果一个符号没有用.globl声明,那么就表示这个符号不会被链接器用到。

  • _start:
    这里定义了_start符号,汇编器在翻译汇编程序时会计算每个数据对象和每条指令的地址,当看到这样一个符号定义时,就把它后面一条指令的地址作为这个符号所代表的首地址。而_start这个符号又比较特殊,它所代表的地址是整个程序的入口地址,所以下一条指令b reset就成了程序中被执行的第一条指令。

  • b reset:
    跳进(不再返回之前地址处)ARM的异常向量表。
    .word(伪操作表示占4字节):8种异常分别占用4个字节,因此每种异常入口处都填写一条跳转指令,直接跳转到相应的异常处理函数中,reset异常是直接跳转到reset函数,其他7种异常则是用ldr将处理函数入口地址加载到pc中。

L1 I/D cache失效

1)什么是cache

  • Cache 是位于 CPU与主存储器DRAM之间的少量超高速静态存储器 SRAM(static RAM),
    其是为了解决 CPU 与主存之间速度匹配问题而设置。
  • Cache又分为I-cache(用来存指令)和D-cache(用来存数据)

2)为什么要让cache失效
因为在使用cache的时候要经过一系列的初始化配置,cache在没配置之前是不能使用的。所以我们要关闭cache,但是在关闭cache之前cache里面可能已经有数据了,为了不影响我们的代码,所以要先让其失效,再进行关闭。

关闭MMU和cache

1) 什么是MMU:

MMU就是负责虚拟地址(virtual address)转化成物理地址(physical address)。

在这里肯定有人跟我一样的疑惑,既然有物理地址我们访问的时候访问物理地址不就完事了吗?为什么要有虚拟地址的存在,然后还要加个专门的硬件去转换,这就是多此一举吗?
其实加入了虚拟地址后有下面两个作用

  • 虚拟内存:有了虚拟内存,可以在处理器上运行比实际物理内存大的应用程序。
  • 内存保护:根据需要对特定的内存区块的访问进行保护,通过这一功能,我们可以将特定的内存块设置成只读、只写或是可同时读写。

2)为什要关闭MMU
跟cache的原因一样,在使用MMU之前要进行一系列的初始化,并且过程比较复杂,现在用不到MMU和cache,所以要关闭它们。

start.S代码注释

/*
 * start.S
 */

/*
 * Exception vector table:异常向量表b reset
 */
 
.text//伪操作

	.global	_start//声明一个_start全局符号
_start:
	b reset//构造异常向量表->跳转到复位异常处理函数
	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
//异常处理函数
_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

 /* The actual reset code,Exception vector table:异常向量表->复位代码 */
reset:
	/* Set Vector Base Address Register:设置矢量寄存器基地址,重新映射异常向量表 */
	ldr	r0,=0x43c00000
	mcr	p15,0,r0,c12,c0,0		@ Vector Base Address Register
	mrc p15, 0, r0, c1, c0, 0
	bic r0, #(1<<13)
	mcr p15, 0, r0, c1, c0, 0

	/* Set the cpu to svc32 mode:将CPU设置为SVC模式10011,禁止fiq,irq则为1101 0011 = 0xd3 */
	mrs r0, cpsr
	bic r0, r0, #0x1f
	orr r0, r0, #0xd3
	msr cpsr, r0

	/* Enable NEON/VFP unit:使能NEON/VFP单元 */
	mrc p15, #0, r1, c1, c0, #2
	orr r1, r1, #(0xf << 20)
	mcr p15, #0, r1, c1, c0, #2
	mov r1, #0
	mcr p15, #0, r1, c7, c5, #4
	mov r0, #0x40000000
	fmxr fpexc, r0

	/* Cache init:高速缓存cache初始化 */
	mrc	p15, 0, r0, c0, c0, 0
	and	r1, r0, #0x00f00000
	and	r2, r0, #0x0000000f
	orr r2, r2, r1, lsr #20-4
	cmp r2, #0x30
	mrceq p15, 0, r0, c1, c0, 1
	orreq r0, r0, #0x6
	mcreq p15, 0, r0, c1, c0, 1

	/* Invalidate L1 I/D :让L1的I/D cache失效*/
	mov r0, #0
	mcr	p15, 0, r0, c8, c7, 0
	mcr	p15, 0, r0, c7, c5, 0

	/* Disable mmu stuff and caches :关闭MMU和cache */
	mrc p15, 0, r0, c1, c0, 0
	bic r0, r0, #0x00002000
	bic r0, r0, #0x00000007
	orr r0, r0, #0x00001000
	orr r0, r0, #0x00000002
	orr r0, r0, #0x00000800
	mcr p15, 0, r0, c1, c0, 0

	/* Initialize stacks:初始化栈 */

init_stack://栈满减
	ldr	r0, stacktop        /*get stack top pointer:指向栈顶*/

	/********svc mode stack********/
	mov	sp, r0		//将栈顶地址赋值给栈指针寄存器R13:sp
	sub	r0, #128*4  /*512 byte  for irq mode of stack:将R0中的值减去128*4字节重新赋值给R0*/
	/********irq mode stack********/
	msr	cpsr, #0xd2
	mov	sp, r0
	sub	r0, #128*4          /*512 byte  for fiq mode of stack*/
	/********fiq mode stack********/
	msr	cpsr, #0xd1
	mov	sp, r0
	sub	r0, #0
	/********abort mode stack******/
	msr	cpsr, #0xd7
	mov	sp, r0
	sub	r0, #0
	/********undefine mode stack**/
	msr	cpsr, #0xdb
	mov	sp, r0
	sub	r0, #0
    /***sys mode and usr mode stack***/
	msr	cpsr, #0x10
	mov	sp, r0             /*1024 byte  for user mode of stack*/

    /******clear bss section:清除bss段********/
	ldr	r0, =__bss_start	/* this is auto-relocated! */
	ldr	r1, =__bss_end__	/* this is auto-relocated! */
	mov	r2, #0x00000000		/* prepare zero to clear BSS */

clbss_l: cmp r0, r1			/* while not at end of BSS */
	strlo r2, [r0]			/* clear 32-bit BSS word */
	addlo r0, r0, #4		/* move to next */
	blo	clbss_l

	/* Call _main :跳进C:main主函数*/
	b main


/*
 * Exception handlers:异常处理函数
 */
	.align 5  // align 5:表示2的5次方=32bit,也就是4字节对齐 = .word
undefined_instruction:
	b	.	//跳转到当前文件中查找undefined_instruction的地址

	.align 5
software_interrupt:
	b	.

	.align 5
prefetch_abort:
	b	.

	.align 5
data_abort:
	b	.

	.align 5
not_used:
	b	.

	.align 5
	.global irq
irq:
	sub  lr, lr, #4
	stmfd sp!, {r0-r12, lr}
	.weak do_irq
@ 	bl do_irq
	ldmfd sp!, {r0-r12, pc}^

	.align 5
	.global fiq
fiq:
	sub  lr, lr, #4
	stmfd sp!, {r0-r12, lr}
	.weak do_fiq
@	bl do_fiq
	ldmfd sp!, {r0-r12, pc}^

stacktop:    .word 		stack + 4 * 512	//栈顶
.data

stack:	 .space  4 * 512	//申请的栈空间大小

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值