☀️作者简介:大家好我是汤姆凯特,大家可以叫我汤姆
🐋个人主页:IM汤姆凯特的优快云博客
🎁系列专栏:【ARM嵌入式基础】
🌱每日一句:不要试图鹤立鸡群,离开那群鸡。
文章目录
求三个数的阶乘并求和
求解这个问题的目的是:练习汇编中子程序的建立和调用。
想求三个数的阶乘并求和,一共分为两个步骤,先对三个阶乘分别求阶乘,然后将三个数求和并输出,下面分步骤详解。
一、用子程序求阶乘
1.确定子程序的输入值
先定义全局变量
.data
a:.word 2
b:.word 3
c:.word 4
将r0作为子程序的输入,因此每次都先将待求阶乘的数取到寄存器r0
ldr r0,=a
ldr r0,[r0]
然后用跳转指令进入子程序
bl fact
2.循环累乘求解
先给子程序构建框架
fact:
push {lr}
......
pop {lr}
mov pc,lr
.end
累乘的值存到寄存器r8,给r8赋初始值
mov r8,#1
用待求阶乘数作为循环递减变量
loop:
mul r8,r0
sub r0,#1
cmp r0,#0
bne loop
3.确定返回主程序的返回值
累乘后的值存放在r8,因此可以直接将r8作为返回值
二、3个数分别调用子程序
1.从内存取到值作为子程序输入
3个值存放在内存变量中分别叫“a,b,c”
ldr r0,=a
ldr r0,[r0]
bl fact
ldr r0,=b
ldr r0,[r0]
bl fact
ldr r0,=c
ldr r0,[r0]
bl fact
2.将3个数暂存到r1~r3
将“a,b,c”三个还没有求阶乘的数,在进入子程序前暂存到r1~r3用于输出(可以看到输出的格式串中有四个数据,所以最后一个数据需要用到压栈)
.data
fmt:.asciz "\n %d!+ %d!+ %d!=%d\n"
main:
mov r1,r0
bl fact
mov r2,r0
bl fact
mov r3,r0
bl fact
3.将返回值存到指定寄存器
每一个调用子程序求完的值都在r8,要先将这个值暂存到3个寄存器中用于求和
bl fact
mov r4,r8
bl fact
mov r5,r8
bl fact
mov r6,r8
三、三个数求和
1.两两求和
现在三个求完阶乘的数据分别存放在r4~r6,对这三个数相加并放到r8中
add r8,r4,r5
add r8,r8,r6
2.压栈输出,出栈结束
在输出格式串中用到了四个数据,所以需要把第四个数据压到栈顶,然后输出完r1~r3之后,输出栈顶数据。那因此就是将r8压入栈顶。
//fmt:.asciz "\n %d!+ %d!+ %d!=%d\n"
push {r8}
ldr r0,=fmt
bl printf
pop {r8}
完整代码
.data
a:.word 2
b:.word 3
c:.word 1
fmt:.asciz "\n %d!+ %d!+ %d!=%d\n"
.text
.globl main
main:
push {lr}
//调用3次子程序
ldr r0,=a
ldr r0,[r0]
mov r1,r0
bl fact
mov r4,r8
ldr r0,=b
ldr r0,[r0]
mov r2,r0
bl fact
mov r5,r8
ldr r0,=c
ldr r0,[r0]
mov r3,r0
bl fact
mov r6,r8
//三个数求和存到r8
add r8,r4,r5
add r8,r8,r6
push {r8}
ldr r0,=fmt
bl printf
mov r0,#0
pop {lr}
mov pc,lr
//子程序fact
//r0作为子程序的入口参数
//r8作为返回值
fact:
push {lr}
mov r8,#1
loop:
mul r8,r0
sub r0,#1
cmp r0,#0
bne loop
pop {lr}
mov pc,lr
.end