汇编代码杂记

一直没有在汇编中写过代码。而且读一些复杂的代码,还有一些吃力。并且自己在ARM体系结构方面的基本功非常薄弱,仅仅是看过杜春雷同学写的那本《ARM体系结构与编程》的教材,偶尔看一下网上同学总结的一些ARM指令的野史笔记。

由于要追踪一下项目中页表的建立流程,由于枝叶比较繁茂,并且深入汇编代码之中,因此,不能充分利用野蛮并且笨拙的Printk,于是便需要在汇编中调用自己写的C函数,然后让流程重新回到汇编中,继续徜徉。

让汇编调用C中的函数,在网上的文章一抓一大把,可是让C中的函数重新返回到汇编中,不着痕迹得继续运行,却没有这样的总结性文章。无奈之下,重新从download.csdn.net中下载到ARM指令集(以前看过,但由于一次误操作,将之永久驱逐出俺的硬盘中),By the way,这个ARM指令集确实不错,有需要的同学到csdn资源中心去自己寻找吧。下面把俺的情况说一下:
ENTRY(cpu_arm926_set_pte_ext)

mov r3, r1

eor     r3, r3, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY

bic     r2, r3, #PTE_SMALL_AP_MASK

bic     r2, r2, #PTE_TYPE_MASK

orr     r2, r2, #PTE_TYPE_SMALL

tst     r3, #L_PTE_USER                 @ User?

orrne   r2, r2, #PTE_SMALL_AP_URO_SRW

tst     r3, #L_PTE_WRITE | L_PTE_DIRTY  @ Write and Dirty?

orreq   r2, r2, #PTE_SMALL_AP_UNO_SRW

tst     r3, #L_PTE_PRESENT | L_PTE_YOUNG        @ Present and Young?

movne   r2, #0

b  hypervisor_set_pte

我要做的事情是,在hypervisor_set_pte之前调用一个自写的C函数。由于后面还有b hypervisor_set_pte.而hypervisor_set_pte这个函数返回后,返回到lr所指定的地址中去,因此在调用自写的C函数时,必须要保存lr的值。
至此,在b hypervisor_set_pte之前加上:
stmfd sp!, {lr}

bl test

ldmfd sp!, {lr}

这样似乎很完美了。可是编译执行后,虽然是完成了test函数的功能,但却出现了取值异常。根据分析,不应该出现得啊。后来,经过同学的分析,是不是有可能破坏了其他的寄存器?我测试了一下,把r0清0后,然后b hypervisor_set_pte,编译运行的结果也出现错误,显然,确实是其他寄存器需要被hypervisor_set_pte使用。于是,
stmfd sp!,{r0,lr}

bl test

ldmfd sp!,{r0,lr}

编译运行的结果仍然不正确。索性,
stmfd sp!, {r0-r12, lr}

bl test

ldmfd sp!, {r0-r12, lr}

编译运行后,哦,世界一片宁静。太棒了。
由此,写汇编一定要仔细,谨慎。尽量做到万无一失,就好似做POJ上的题目,每一种条件都要想到,否则一直WA。通过这个错误,马上连想到,第一次写驱动时,malloc后忘记free的窘状,明明一切逻辑都正确,为什么运行不起来?哦,原来是内存耗完了。

写此篇,以纪念在ARM汇编中写上第一行代码。

评论

此博客中的热门博文

Linux/ARM Page Table Entry 属性设置分析

提交了30次才AC ---【附】POJ 2488解题报告

笔记