嵌入式bootloader开发Tiny6410(3)

在上一篇中依赖于C语言函数,简单的演示了如何在uboot下运行hello,world代码,但是在实际编写底层代码的时候,很多情况下都需要使用到汇编语言,汇编语言是为了方便人类记忆机器指令而发明的一种语言,它和机器指令是一一对应的关系。

ARM从大的方向上来讲属于RISC指令体系结构,指令集相对容易掌握,下面主要通过将上一篇中的代码用汇编语言实现来试图掌握汇编语言的写法。在此之前,需要介绍一些基础性的概念:

函数调用规范:函数间相互调用时需要遵循的一套标准。ARM做了如此规定(APCS)如果要实现函数调用必须遵守其约定。

 

下面是编写的示例代码1:

=====================================================================================

sub sp,sp,#4 @sp=sp-4
str r14,[sp]@把返回值存储到sp-4处


ldr r0,=fmt
mov r14,r15 @mov lr,pc
ldr r15,show @call show


ldr r14,[sp]
add sp,sp,#4@恢复sp值
mov r15,r14 @mov pc,lr


show:
.word 0xc7e13140
fmt:
.asciz "hello,world,ARM asm\n"@ascii不自动加0,asciz自动加0

======================================================================================

在此代码中,使用了堆栈,并将返回值存储到堆栈上,然后再调用函数show显示字符串,其中参数传递由r0~r3传递,超过4个参数通过栈传递

此代码中sp的值只用了一次,不能适应在过程调用中动态开辟空间来存放临时数据的情况,故改进如下:

==========================================================================================

mov ip,sp@将sp保存到ip
sub sp,sp,#12 @sp=sp-12
str r14,[sp]@把返回值存储到sp-4处
str ip,[sp,#4]@存储原来的ip到sp+4处
str fp,[sp,#8]@存储原来的fp到sp+8处


sub fp,ip,#4@设置fp初始值


ldr r0,=fmt
mov r14,r15 @mov lr,pc
ldr r15,show @call show

sub sp,sp,#1000


ldr lr,[fp,#-8]@恢复r14的值,原来的lr
ldr ip,[fp,#-4]@恢复ip的值,ip中保存着原来的sp值
ldr fp,[fp,#0]@恢复fp


mov sp,ip @恢复sp值
mov r15,r14 @mov pc,lr


show:
.word 0xc7e13140
fmt:
.asciz "hello,asm!\n"

==============================================================================================

在此代码中引入了新的寄存器ip,fp,ip用来保存原来的sp,方便堆栈回收,fp用于指示栈底,属于不变量。

==============================================================================================

@程序目的:输出hello,asm字符串
@Author:jefby
@Email:jef199006@gmail.com
mov ip,sp@将sp保存到ip
stmfd sp!,{fp,ip,lr,pc}@store order:pc->lr->ip->fp,若在sp前加!,则更新sp的值,存储pc是为了调试
sub fp,ip,#4


ldr r0,=fmt
mov r14,r15 @mov lr,pc
ldr r15,show @call show

sub sp,sp,#1000

sub sp,fp,#12@先恢复sp到fp-12的位置
ldmfd sp,{fp,sp,pc}@ip->sp,lr->pc


show:
.word 0xc7e13140
fmt:
.asciz "hello,stack-asm!\n"

========================================================================

虽然上述代码也可以运行,但是ARM为了方便提供了更加简单高效的指令stmfd和ldmfd来满足此需要。

===================================================================================

@程序目的:输出hello,asm字符串
@Author:jefby
@Email:jef199006@gmail.com
abc:
mov ip,sp
stmfd sp!,{fp,ip,lr,pc}
sub fp,ip,#4

ldr r0,=test
mov lr,pc
mov pc,r0


sub sp,fp,#12
ldmfd sp,{fp,sp,pc}


test:
mov ip,sp@将sp保存到ip
stmfd sp!,{fp,ip,lr,pc}@store order:pc->lr->ip->fp,若在sp前加!,则更新sp的值,存储pc是为了调试
sub fp,ip,#4


ldr r0,=fmt
mov r14,r15 @mov lr,pc
ldr r15,show @call show

sub sp,sp,#1000

sub sp,fp,#12@先恢复sp到fp-12的位置
ldmfd sp,{fp,sp,pc}@ip->sp,lr->pc


show:
.word 0xc7e13140
fmt:
.asciz "hello,stack-asm!\n"

=========================================================================================

在本程序中使用了类似于C语言中函数的概念,在abc函数中调用test函数.

另外还有新的调用方法分别是b test和bl test(增加了一句mov lr,pc)

具体执行图如下:

嵌入式bootloader开发Tiny6410

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/552a31ae52b091d572ef6ed781433166.html