一起分析Linux系统设计思想——03内核启动流程分析(三)

在学习资料满天飞的大环境下,知识变得非常零散,体系化的知识并不多,这就导致很多人每天都努力学习到感动自己,最终却收效甚微,甚至放弃学习。我的使命就是过滤掉大量的垃圾信息,将知识体系化,以短平快的方式直达问题本质,把大家从大海捞针的痛苦中解脱出来。

4 lookup_processor_type剖析(接上篇)

4.1 DB/IA寻址方式

4.1.1 DB寻址方式

DB(Decrease Before)寻址方式就是在传送数据之前地址递减。下面举例说明。

stmdb r0, {r1-r3} @ 示例汇编代码

汇编代码的伪代码如下:

start_address = Rn - (Number_Of_Set_Bits_In(register_list)*4) = r0 - 3*4 = r0 - 12
end_address = Rn - 4 = r0 -4

if ConditionPassed(cond) then
     address = start_address
     for i = 0 to 15                @ 遍历所有的寄存器
         if register_list[i] == 1   @ 如果在寄存器列表中
              Memory[address] = Ri  @ 将寄存器中的值存储到内存中
              address = address + 4 @ 地址加4,这里是加不是减是因为start_address的计算方式导致的

4.1.2 IA寻址方式

IA(Increase After)寻址方式就是在传送数据之后地址增加。下面举例说明。

ldmia r0, {r1-r3} @ 示例汇编代码

汇编代码的伪代码如下:

start_address = Rn = r0
end_address = Rn + (Number_Of_Set_Bits_In(register_list)*4) - 4 = r0 + 3*4 - 4 = r0 + 8

if ConditionPassed(cond) then
     address = start_address
     for i = 0 to 15                @ 遍历所有的寄存器
         if register_list[i] == 1   @ 如果在寄存器列表中
              Ri = Memory[address,4]@ 将内存中的值传送到寄存器中
              address = address + 4 @ 地址加4

4.2 STMFD/LDMFD与压栈弹栈

4.2.1 STMFD指令

stmfd指令和stmdb指令类似,都使用DB寻址方式。下面以一个示例对stmfd指令进行说明。

指令示例如下:

stmfd sp!, {r4-r7, r9, lr}

该示例的伪代码(只演示逻辑,和真正的压栈顺序可能有所不同)如下:

SP = SP - 6×4;            @ sp最终指向栈顶(sp的值进行改变是指令中的!指示的)
address = SP;               @ 这里的address为start_address
for i = 4 to 7, 9           @ 通用寄存器r4,r5,r6,r7和r9
    Memory[address] = Ri;   @ 将通用寄存器中的值压入到栈中
    address  = address + 4; @ 地址加4(这里是加不是减是由start_address的计算来决定的)
Memory[address] = LR;       @ 将lr寄存器的值也进行压栈(而且必须放在局部栈的栈底),为了保证函数可以返回

压栈过程示意图如下:

在这里插入图片描述

Tips:寄存器列表与内存单元的对应关系:编号低的寄存器对应于内存中低地址单元;编号高的寄存器对应于内存中高地址单元。


4.2.2 LDMFD指令

ldmfd指令和ldmia指令类似,都使用IA寻址方式。下面以一个示例对ldmfd指令进行说明。

指令示例如下:

ldmfd sp!, {r4-r7, r9, pc}

该示例的伪代码(仅演示逻辑)如下:

address = SP;               @ 这里的address为start_address
for i = 4 to 7, 9           @ 通用寄存器r4,r5,r6,r7和r9
    Ri = Memory[address,4]; @ 将通用寄存器中的值从栈中弹出到寄存器中
    address  = address + 4; @ 地址加4
PC = Memory[address,4];     @ 将lr的值(局部栈的栈底存放的是lr的值),令函数返回
SP = address + 4;               @ 将end_address+4赋值给SP

弹栈过程示意图如下:


4.3 lookup_processor_type函数分析

lookup_processor_type函数是__lookup_processor_type 函数的C语言格式,所以需要在 __lookup_processor_type的基础上增加压栈和弹栈,以及入参和返回值的处理代码。有了上述指令的详细分析作铺垫,该函数就不难理解了,详见代码注释。

Tips:Arm9汇编和C语言少量传参和返回值一般使用寄存器r0-r3。

/*
 * This provides a C-API version of the above function.
 */
ENTRY(lookup_processor_type)
	stmfd	sp!, {r4 - r7, r9, lr}  @ 压栈操作(ARM为满减栈),保存现场
	mov	r9, r0      @ r0是C语言调用汇编时的入参,cpuid
	bl	__lookup_processor_type
	mov	r0, r5      @ r0是C语言调用汇编时的出参,pro_info_list指针
	ldmfd	sp!, {r4 - r7, r9, pc}  @ 弹栈操作,恢复现场

<完>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

穿越临界点

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值