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