asm1_a.s:
Reset_Handler ; 代码入口点
ldr sp, =stack_top ; R13:0x00000000---->0x30200000
mov r0, #x ; R0 :0x00000000---->0x0000002D
str r0, [sp] ; 将R0的值存到栈顶,栈顶值:0x00000000---->0x0000002D
mov r0, #y ; R0 :0x0000002D---->0x00000040
ldr r1, [sp] ; 从栈顶读取数据到R1,R1:0x00000000---->0x0000002D
add r0, r0, r1 ; R0 = R0 + R1,R0:0x00000040---->0x0000006D
str r0, [sp] ; 将新的R0值存回栈顶,栈顶值:0x0000002D---->0x0000006D
asm1_b.s:
x EQU 45 ;/* x=45 /
y EQU 64 ;/ y=64 /
z EQU 87 ;/ z=87 /
stack_top EQU 0x30200000 ;/ define the top address for stacks*/
EXPORT Reset_Handler
AREA text,CODE,READONLY
Reset_Handler
mov r0, #x ;/* R0:0x00000000---->0x0000002D /
mov r0, r0, lsl #8 ;/ R0左移8位:0x0000002D---->0x00002D00 /
mov r1, #y ;/ R1:0x00000000---->0x00000040 /
add r2, r0, r1, lsr #1 ;/ R2 = R0 + (R1 >> 1),R2:0x00000000---->0x00002000 /
ldr sp, =stack_top ;/ SP:0x00000000---->0x30200000 /
str r2, [sp] ;/ 栈顶存R2值:0x00000000---->0x00002000 /
mov r0, #z ;/ R0:0x00000000---->0x00000057 /
and r0, r0, #0xFF ;/ R0与0xFF进行AND操作:0x00000057---->0x00000057 /
mov r1, #y ;/ R1:0x00000040---->0x00000040 /
add r2, r0, r1, lsr #1 ;/ R2 = R0 + (R1 >> 1),R2:0x00000057---->0x0000007F /
ldr r0, [sp] ;/ 从栈顶载入R0,R0:0x00000000---->0x00002000 /
mov r1, #0x01 ;/ R1:0x00000000---->0x00000001 /
orr r0, r0, r1 ;/ R0 = R0 OR R1,R0:0x00002000---->0x00002001 /
mov r1, r2 ;/ R1:0x00000000---->0x0000007F /
add r2, r0, r1, lsr #1 ;/ R2 = R0 + (R1 >> 1),R2:0x00002001---->0x00002040 */
asm_code1.s:用于将一定数量的数据从一个源地址复制到一个目标地址的内存块复制例程。这里采用了两种复制方法:一种是八字(word)批量复制,另一种是单字复制。
GLOBAL Reset_Handler ;/使 Reset_Handler 符号对其他文件可见。/
area start,code,readwrite ;/定义一个名为 start 的区域,包含代码,且可以读写。/
entry ;/* 指定程序的入口点*/
code32 ;/指定代码为 ARM 32位模式/
num EQU 20 ;/* 设置要复制的字数 /
Reset_Handler
ldr r0, =src ;/ R0:0x00000000–>src地址 /
ldr r1, =dst ;/ R1:0x00000000–>dst地址 /
mov r2, #num ;/ R2:0x00000000–>0x00000014 (20) /
ldr sp, =0x30200000 ;/ SP:0x00000000–>0x30200000 /
blockcopy
movs r3, r2, LSR #3 ;/ R3:20 (0x14) 右移3位,得到复制的8字倍数 /
beq copywords ;/ 如果R3为0,跳转到copywords /
stmfd sp!, {r4-r11} ;/ 保存工作寄存器r4-r11到栈 /
octcopy 八字块复制
ldmia r0!, {r4-r11} ;/ 从src加载8个字到r4-r11,存储到 dst*/
stmia r1!, {r4-r11} ;/* 将r4-r11存储到目的地址 /
subs r3, r3, #1 ;/ R3自减1 /
bne octcopy ;/ 如果R3不为0,继续复制 /
ldmfd sp!, {r4-r11} ;/ 恢复寄存器r4-r11 /
copywords 单字复制
ands r2, r2, #7 ;/ R2与7进行AND操作,得到需要额外复制的字数 /
beq stop ;/ 如果R2为0,跳转到stop /
wordcopy 单字复制
ldr r3, [r0], #4 ;/ 从源地址加载一个字到R3 /
str r3, [r1], #4 ;/ 将一个字从R3存储到目的地址 /
subs r2, r2, #1 ;/ R2自减1 /
bne wordcopy ;/ 如果R2不为0,继续复制 */
asm_code2.s:功能调用机制,包括一个跳转表,用于根据输入参数决定执行加法或减法操作。
Reset_Handler
mov r0, #0 ;/* R0:0x00000000–>0x00000000 /
mov r1, #3 ;/ R1:0x00000000–>0x00000003 /
mov r2, #2 ;/ R2:0x00000000–>0x00000002 /
bl arithfunc ;/ 调用arithfunc函数 使用链接寄存器lr存储返回地址*/
stop
b stop ;/* 无限循环停止 /
arithfunc ;/ 标记函数开始 /
cmp r0, #num ;/ 比较R0与num /
bhs DoAdd ;/ 如果R0>=2,执行DoAdd操作 */
adr r3, JumpTable ;/* R3:加载跳转表的地址 */
ldr pc, [r3,r0,LSL#2] ;/* 根据R0的值乘以4偏移,跳转到相应的例程 */
JumpTable
dcd DoAdd ;/* 跳转表条目:指向DoAdd /
dcd DoSub ;/ 跳转表条目:指向DoSub /
D
add r0, r1, r2 ;/ R0 = R1 + R2,R0:0x00000005 /
bx lr ;/ 返回到调用函数后的指令位置 /
DoSub
sub r0, r1, r2 ;/ R0 = R1 - R2,R0:0x00000001 /
bx lr ;/ 返回到调用函数后的指令位置 /
end ;/ 文件结束标记 */