ARM程序设计
ARM程序设计
一、if/else 如何实现的
if (a > b)
{
c = 5;
}
else
{
c = 6;
}
可以加个:if ( likely(a > b) )
{}
else
{}
likely(x) :编译器的修饰词,告诉编译器,后面的这个表达式x很有可能成立
unlikely(x):编译器的修饰词,告诉编译器,后面的这个表达式x不太可能成立
编译器会选择? //上面的代码,明显会选择第一种编译方式
二、循环是如何实现的
for (i = 1, sum = 0; i <= 10;i++)
{
sum = sum + i;
}
=>
初始条件 i--R01,sum--R10
循环条件:R0<=10 ---CMP R0,#10 LE 就执行循环 GT 跳出循环 (到结束的地方lable) B
CMP 之后一定要写循环条件不满足的情况,跳出
循环体:用两个标号,分别标识循环体的开始和结束。只用一个标号,也可以,标识循环体的开始
loop_sum
ADD R1,R1,R0
ADD R0,R0,#1
loop_sum_end
难点在于循环条件
1.循环条件写入循环体,初始条件写在循环体外
2.不满足跳出 B end ,满足顺序执行
3.循环体末尾 无条件不返回跳到循环开始的位置 B loopstart
练习:计算100以内所有数之和。
参考代码:
code_start
MOV R0,#1 ;i=1
MOV R1,#0 ;sum=0
loop_s
CMP R0,#100
BGT loop_end ;not satisfic,run away
ADD R1,R1,R0
ADD R0,R0,#1
B loop_s
loop_end
B .
END
三、过程调用(函数调用)
1、构成
PROC …… ENDP z构成一个过程
ATPCS: ARM/Thumb Procedure Call Standard
ARM/Thumb过程调用标准
ARM定的.
记住:过程调用就是这样
label PROC
PUSH
(看你的)
POP
ENDP
2、理解难点
(1)入口参数传送用 R0, R1,R2, R3,如果超过4个参数,后面的参数需要放到栈空间
R0:对应第一个参数 R1:第二个参数……
一定要把参数放到R0-R3,并且按顺序,第一个参数一定是R0
(2) 函数的返回值用R0,如果超过32bits,例如64bits,用R1(高32位) R0(低32位)
提醒:R0是返回值,返回值只能放到R0中,所以在实现过程中,你要记住R0不要乱用。如果真的用了,就要赶快找 个替身给R0
"单值类型",只能返回一个值
(3) 函数实现
“现场保护” PUSH R0-R12 LR
Reglists -> 栈 PUSH {寄存器列表}
传递参数的那几个寄存器你不需要保护, why?
因为那几个寄存器本身就是传递给你用的,你无须保护。
建议: 非参数寄存器(除了SP,PC)都要保存,偷懒的话,除了参数占用的寄存器,其余全部保护
假设你的过程参数用R0,R1
PUSH {R2-R12,LR} //R14LR也要保存,否则在过程中,就不能调用其他过程啦。R14(LR)一定要保护,因为调用过程一定有返回,有返回就要记住回来的路,这是回来的路
"现场恢复" POP
POP {R2-R12, PC} //直接把R14(LR)的值恢复到R15(PC)
3、练习:
写一个过程调用 计算两个数之和
参考代码: 这里特别提醒一下,test_start PROC ……ENDP
code_start PROC
MOV R0,#3
MOV R1,#5
BL sum_two
B .
ENDP
sum_two PROC
PUSH {R2-R12,LR}
ADD R0,R0,R1
POP {R2-R12,PC}
ENDP
END
四、汇编文件 与 C文件共存
1、汇编中如何调用C代码
(1)首先建一个.c文件

(1)需要在汇编文件,"进口":引入相应的全局变量名或全局函数, “符号”
IMPORT 函数名or全局变量名
(不是写在代码段,写在堆栈段、数据段或者向量表下面)

(2)直接调用就好
BL sum_three

注意:汇编中调用C语言,是把最近的寄存器作为C语言的输入,例如C语言有两个参数,则是把R0,R1作为输入
2、C文件中如何调用汇编
(1)申明是外部函数 例如:extern int sum_two(int, int);
(2)直接调用汇编过程(写对应的过程名就好)
(3)回到汇编代码中还需要说明该函数是“出口”函数
需要用EXPORT把相应的全局变量名或全局函数名,导出
EXPORT sum_two

3、练习
(1)计算三个数相加,求和 要求用C和汇编代码协调实现。
目前在汇编中已经有了一个计算两个数之和的代码sum_two了。
只需要写一个C代码 int sum_three(int a, int b, int c) 在其中调用汇编的sum_two
① .s文件
stack_size EQU 0x200
vector_size EQU 0x400
; define stack
AREA mystack, DATA, READWRITE
stack_start
SPACE stack_size
stack_end
PRESERVE8
;define vectors
AREA RESET, DATA, READONLY
vectors
DCD stack_end ;stack-top
DCD code_start ;begin code
SPACE vector_size
vectors_end
IMPORT sum_three
EXPORT sum_two
;define data
AREA mydata, DATA, READWRITE
data_s
SPACE 4
;define code
AREA mycode, CODE, READONLY,ALIGN=3
code_start PROC
MOV R0,#3
MOV R1,#5
MOV R2,#8
BL sum_three
B .
ENDP
sum_two PROC
PUSH {R2-R12,LR}
ADD R0,R0,R1
POP {R2-R12,PC}
ENDP
END
②.c
extern int sum_two(int,int);
int sum_three(int a,int b,int c)
{
return c+sum_two(a,b);
}
五、作业:
1. 用汇编语言实现一个函数,判断a是否为b的倍数
输入:a、b
输出:是倍数 1 不是倍数 0
分析:CMP---LT END---SUB/ADD ---CMP EQ=1 NE=0
ADD: a=b+b a=b+b+b…… i从1开始增加,a=ib则a是b的倍数
SUB:a-b a-2b …… a-ib,直到a-b=0则a是b的倍数
C:
/*
return 1: a是b的倍数
return 0: a不是b的倍数
*/
int Is_Multi(int a, int b) //3,2
{
int t = b; //2
while (a>= b)
{
if (a == b)
{
return 1;
}
b = b + t;
}
return 0;
}
int a=7,b=3,i=b=3 a>=b(7>=3),a!=b,b=b+t=3+3=6 7>=6,7!=6,b=6+t=6+3=9 7<9,return 0
(1) 加法实现:
stack_size EQU 0x200
vector_size EQU 0x400
; define stack
AREA mystack, DATA, READWRITE
stack_start
SPACE stack_size
stack_end
PRESERVE8
;define vectors
AREA RESET, DATA, READONLY
vectors
DCD stack_end ;stack-top
DCD code_start ;begin code
SPACE vector_size
vectors_end
;define data
AREA mydata, DATA, READWRITE
data_s
SPACE 4
;define code
AREA mycode, CODE, READONLY,ALIGN=3
code_start PROC
MOV R0,#7
MOV R1,#3
BL is_Multi
B .
ENDP
is_Multi PROC
PUSH {R2-R12,LR}
MOV R2,R0 ;R2=a
MOV R3,R1 ;R3=t R1=b
MOV R0,#0
loop_s
CMP R2,R1 ;a>=b
BLT loop_end ;LT <,a<b
MOVEQ R0,#1
BEQ loop_end
ADD R1,R1,R3 ;b=b+t
B loop_s
loop_end
POP {R2-R12,PC}
ENDP
END
(2)、测试 (加法)
①a=7,b=3



②a=8,b=2

(3)减法实现
stack_size EQU 0x200
vector_size EQU 0x400
; define stack
AREA mystack, DATA, READWRITE
stack_start
SPACE stack_size
stack_end
PRESERVE8
;define vectors
AREA RESET, DATA, READONLY
vectors
DCD stack_end ;stack-top
DCD code_start ;begin code
SPACE vector_size
vectors_end
;define data
AREA mydata, DATA, READWRITE
data_s
SPACE 4
;define code
AREA mycode, CODE, READONLY,ALIGN=3
code_start PROC
MOV R0,#8
MOV R1,#2 ;R1=b
BL is_Multi
B .
ENDP
is_Multi PROC
PUSH {R3-R12,LR}
MOV R2,R0 ;R2=a ,replace R0,R0 will be return value
MOV R0,#0 ;initialize
loop_s
CMP R2,R1 ;a>=b
BLT loop_end ;a<b
MOVEQ R0,#1 ;a=0,R0=1
BEQ loop_end ;return 1
SUB R2,R2,R1 ;a=a-b
B loop_s
loop_end
POP {R2-R12,PC}
ENDP
END
(4)测试(减法)
①a=7,b=3
②a=8,b=2
2、用汇编语言实现一个函数,判断一个数x是否为质数
C:
int Is_Prime(int x)
{
int i ;
for (i = 2; i < x; i++)
{
if (Is_Multi(x, i))
{
return 0;
}
}
return 1;
}
(1)、代码实现
stack_size EQU 0x200
vector_size EQU 0x400
; define stack
AREA mystack, DATA, READWRITE
stack_start
SPACE stack_size
stack_end
PRESERVE8
;define vectors
AREA RESET, DATA, READONLY
vectors
DCD stack_end ;stack-top
DCD code_start ;begin code
SPACE vector_size
vectors_end
;define data
AREA mydata, DATA, READWRITE
data_s
SPACE 4
;define code
AREA mycode, CODE, READONLY,ALIGN=3
code_start PROC
MOV R0,#3
BL Is_prime
B .
ENDP
Is_prime PROC
PUSH {R1-R12,LR}
MOV R1,#2;i
MOV R2,R0; R2 = x
loop_prime_s ;for(int i=2;i<x;++i)
CMP R1,R2 ;i x
MOVEQ R0,#1 ; i==x,R0=1
BGE loop_prime_end ;i>=x
;i<x
;if{
MOV R0,R2
BL is_Multi
CMP R0,#1
MOVEQ R0,#0 ;RO==1,x is multi of i,R0=0
BEQ loop_prime_end ;return 0
;}
ADD R1,R1,#1 ;i++
B loop_prime_s ;while
loop_prime_end
POP {R1-R12,PC}
ENDP
is_Multi PROC
PUSH {R1-R12,LR}
MOV R2,R0 ;R2=a ,replace R0,R0 will be return value
MOV R0,#0 ;initialize
loop_multi_s
CMP R2,R1 ;a>=b
BLT loop_multi_end ;a<b
MOVEQ R0,#1 ;a=0,R0=1
BEQ loop_multi_end ;return 1
SUB R2,R2,R1 ;a=a-b
B loop_multi_s
loop_multi_end
POP {R1-R12,PC}
ENDP
END
(2)、测试
①x=9

②x=11

③x=19

④x=21

(3)、分析
①注释
②举例x=3分析过程

…………
3、 用汇编语言实现100以内所有素数之和
提示:
素数就是质数。把100以内所有的质数,都保存在一个数组中。
x是不是质数 拿 < x的所有素数去整除x,即可。
怎么找素数?
2就是最小的素数
定义一个数据段 存放找到的素数
data_prime 2
sum=2
3是素数吗?Is_Multi(3, 2) 返回 0 是素数
3存入
data_prime 2,3
sum=5
4是素数吗?
依次把 2,3 去判断 Is_Multi(4, 2) 返回是1 --4不是素数 4不存入
5是素数吗?
依次把 2,3 去判断 Is_Multi(5, 2) 返回是0 --Is_Multi(5, 3) 返回是 0 5就是素数 存入
data_prime 2,3,5
sum=10
<99 继续……
(1)代码
①错误代码
stack_size EQU 0x200
vector_size EQU 0x400
data_size EQU 0X400
; define stack
AREA mystack, DATA, READWRITE
stack_start
SPACE stack_size
stack_end
PRESERVE8
;define vectors
AREA RESET, DATA, READONLY
vectors
DCD stack_end ;stack-top
DCD code_start ;begin code
SPACE vector_size
vectors_end
;define data
AREA mydata, DATA, READWRITE
data_s
SPACE data_size
;define code
AREA mycode, CODE, READONLY,ALIGN=3
code_start PROC
BL sum_prime
B .
ENDP
sum_prime PROC
PUSH {R1-R12,LR}
MOV R5,#0 ;sum
MOV R4,#1 ;start from 2
LDR R6,=data_s
loop_sum_s
CMP R4,#100
BGT loop_sum_end
BL is_prime
CMP R0,#1
BNE loop_sum_end ;delete
ADD R6,R6,#4 ;add EQ
STR R4,[R6] ;add EQ
ADD R5,R5,R4 ;add EQ
ADD R4,R4,#1
B loop_sum_s
loop_sum_end
POP {R1-R12,PC}
ENDP
is_prime PROC
PUSH {R1-R12,LR}
MOV R1,#2;i
MOV R2,R4; R2 = x
loop_prime_s ;for(int i=2;i<x;++i)
CMP R1,R2 ;i x
MOVEQ R0,#1 ; i==x,R0=1
BGE loop_prime_end ;i>=x
;i<x
;if{
BL is_Multi
CMP R0,#1
MOVEQ R0,#0 ;RO==1,x is multi of i,R0=0
BEQ loop_prime_end ;return 0
;}
ADD R1,R1,#1 ;i++
B loop_prime_s ;while
loop_prime_end
POP {R1-R12,PC}
ENDP
is_Multi PROC
PUSH {R1-R12,LR}
MOV R3,R2
MOV R0,#0
loop_multi_s
CMP R3,R1 ;a>=b
BLT loop_multi_end ;a<b
MOVEQ R0,#1 ;a=0,R0=1
BEQ loop_multi_end ;return 1
SUB R3,R3,R1 ;a=a-b
B loop_multi_s
loop_multi_end
POP {R1-R12,PC}
ENDP
END
②修改后的正确代码
stack_size EQU 0x200
vector_size EQU 0x400
data_size EQU 0X400
; define stack
AREA mystack, DATA, READWRITE
stack_start
SPACE stack_size
stack_end
PRESERVE8
;define vectors
AREA RESET, DATA, READONLY
vectors
DCD stack_end ;stack-top
DCD code_start ;begin code
SPACE vector_size
vectors_end
;define data
AREA mydata, DATA, READWRITE
data_s
SPACE data_size
;define code
AREA mycode, CODE, READONLY,ALIGN=3
code_start PROC
BL sum_prime
B .
ENDP
sum_prime PROC
PUSH {R1-R12,LR}
MOV R5,#0 ;sum
MOV R4,#2 ;start from 2
LDR R6,=data_s
loop_sum_s
CMP R4,#100
BGT loop_sum_end
BL is_prime
CMP R0,#1
ADDEQ R6,R6,#4
STREQ R4,[R6]
ADDEQ R5,R5,R4
ADD R4,R4,#1
B loop_sum_s
loop_sum_end
MOV R0,R5
POP {R1-R12,PC}
ENDP
is_prime PROC
PUSH {R1-R12,LR}
MOV R1,#2;i
MOV R2,R4; R2 = x
loop_prime_s ;for(int i=2;i<x;++i)
CMP R1,R2 ;i x
MOVEQ R0,#1 ; i==x,R0=1
BGE loop_prime_end ;i>=x
;i<x
;if{
BL is_Multi
CMP R0,#1
MOVEQ R0,#0 ;RO==1,x is multi of i,R0=0
BEQ loop_prime_end ;return 0
;}
ADD R1,R1,#1 ;i++
B loop_prime_s ;while
loop_prime_end
POP {R1-R12,PC}
ENDP
is_Multi PROC
PUSH {R1-R12,LR}
MOV R3,R2
MOV R0,#0
loop_multi_s
CMP R3,R1 ;a>=b
BLT loop_multi_end ;a<b
MOVEQ R0,#1 ;a=0,R0=1
BEQ loop_multi_end ;return 1
SUB R3,R3,R1 ;a=a-b
B loop_multi_s
loop_multi_end
POP {R1-R12,PC}
ENDP
END
(2)测试
4.求1000以内的完数,把个数保存到R0,R1-R12保存求出来的完数
提示:如果一个数等于它的因子之和,则称该数为“完数”(或“完全数”)。
例如,6的因子为1、2、3,而 6=1+2+3,因此6是“完数”。
因子就是能被整除的数,(i%j)==0,即i是j的倍数
(1)错误代码
stack_size EQU 0x200
vector_size EQU 0x400
data_size EQU 0X400
; define stack
AREA mystack, DATA, READWRITE
stack_start
SPACE stack_size
stack_end
PRESERVE8
;define vectors
AREA RESET, DATA, READONLY
vectors
DCD stack_end ;stack-top
DCD code_start ;begin code
SPACE vector_size
vectors_end
;define data
AREA mydata, DATA, READWRITE
data_s
SPACE data_size
;define code
AREA mycode, CODE, READONLY,ALIGN=3
code_start PROC
BL pf_count
B .
ENDP
pf_count PROC
MOV R4,#1 ;x start from 1
LDR R6,=data_s
MOV R7,#0 ;cnt
loop_cnt_s
PUSH{LR}
CMP R4,#1000
BGT loop_cnt_end
BL is_perfect
CMP R0,#1
ADDEQ R7,R7,#1
STMIA R6,{R1-R12}
ADDEQ R6,R6,#4
B loop_cnt_s
loop_cnt_end
MOVEQ R0,R7
POP{PC}
ENDP
is_perfect PROC
PUSH {R1-R12,LR}
MOV R3,#1 ;i--b
MOV R5,#0 ;sum
loop_perfect_s
CMP R3,R4 ;i:x
BGE loop_perfect_end
BL is_Multi
CMP R0,#1 ;whether x is multi of i
ADDEQ R5,R5,R3
ADDEQ R3,R3,#1
CMP R5,R4 ;sum:x
MOVEQ R0,#0
BGE loop_perfect_end
B loop_perfect_s
loop_perfect_end
POP {R1-R12,PC}
ENDP
is_Multi PROC
PUSH {R1-R12,LR}
MOV R0,#0
loop_multi_s
CMP R4,R3 ;a>=b
BLT loop_multi_end ;a<b
MOVEQ R0,#1 ;a=b,R0=1
BEQ loop_multi_end ;return 1
SUB R4,R4,R3 ;a=a-b
B loop_multi_s
loop_multi_end
POP {R1-R12,PC}
ENDP
END
(2)正确代码
stack_size EQU 0x200
vector_size EQU 0x400
data_size EQU 0X400
; define stack
AREA mystack, DATA, READWRITE
stack_start
SPACE stack_size
stack_end
PRESERVE8
;define vectors
AREA RESET, DATA, READONLY
vectors
DCD stack_end ;stack-top
DCD code_start ;begin code
SPACE vector_size
vectors_end
;define data
AREA mydata, DATA, READWRITE
data_s
SPACE data_size
;define code
AREA mycode, CODE, READONLY,ALIGN=3
code_start PROC
BL pf_count
B .
ENDP
pf_count PROC
PUSH{LR}
MOV R4,#1 ;x start from 1
LDR R6,=data_s
MOV R7,#0 ;cnt
loop_cnt_s
CMP R4,#1000
BGT loop_cnt_end
BL is_perfect
CMP R0,#1
ADDEQ R7,R7,#1
STREQ R4,[R6]
ADDEQ R6,R6,#4
ADD R4,R4,#1
B loop_cnt_s
loop_cnt_end
MOV R0,R7
LDR R6,=data_s
LDMIA R6,{R1-R12}
POP{PC}
ENDP
is_perfect PROC
PUSH {R1-R12,LR}
MOV R3,#1 ;i--b
MOV R5,#0 ;sum
loop_perfect_s
CMP R3,R4 ;i:x
BGE loop_perfect_end
BL is_Multi
CMP R0,#1 ;whether x is multi of i
ADDEQ R5,R5,R3
ADD R3,R3,#1
B loop_perfect_s
loop_perfect_end
MOV R0,#0
CMP R5,R4 ;sum:x
MOVEQ R0,#1
POP {R1-R12,PC}
ENDP
is_Multi PROC
PUSH {R1-R12,LR}
MOV R0,#0
loop_multi_s
CMP R4,R3 ;a>=b
BLT loop_multi_end ;a<b
MOVEQ R0,#1 ;a=b,R0=1
BEQ loop_multi_end ;return 1
SUB R4,R4,R3 ;a=a-b
B loop_multi_s
loop_multi_end
POP {R1-R12,PC}
ENDP
END
(3)测试
5.判断闰年函数
(1)代码
stack_size EQU 0x200
vector_size EQU 0x400
; define stack
AREA mystack, DATA, READWRITE
stack_start
SPACE stack_size
stack_end
PRESERVE8
;define vectors
AREA RESET, DATA, READONLY
vectors
DCD stack_end ;stack-top
DCD code_start ;begin code
SPACE vector_size
vectors_end
;define data
AREA mydata, DATA, READWRITE
data_s
SPACE 4
;define code
AREA mycode, CODE, READONLY,ALIGN=3
code_start PROC
MOV R0,#2020
BL is_Leapyear
B .
ENDP
is_Leapyear PROC
PUSH {R1-R12,LR}
MOV R1,#400
MOV R2,R0
MOV R0,#0
BL is_Multi
CMP R0,#1
BEQ leap_true
MOV R1,#4
BL is_Multi ;x%4
CMP R0,#1
BNE leap_false
MOV R1,#100
BL is_Multi ;x%100
CMP R0,#1
BEQ leap_false
leap_true
MOV R0,#1
POP {R1-R12,PC}
leap_false
MOV R0,#0
POP {R1-R12,PC}
ENDP
is_Multi PROC
PUSH {R1-R12,LR}
MOV R3,R2
MOV R0,#0
loop_multi_s
CMP R3,R1 ;a>=b
BLT loop_multi_end ;a<b
MOVEQ R0,#1 ;a=0,R0=1
BEQ loop_multi_end ;return 1
SUB R3,R3,R1 ;a=a-b
B loop_multi_s
loop_multi_end
POP {R1-R12,PC}
ENDP
END
(2)注释
(3)测试
①2022

②2021

③1978
④2000

6.求最近质数函数
;求一个正整数n的最近质数,如果n本身就是质数,则返回本身,
;如果有两个最近质数,返回较小的哪个。
7、求水仙花数
(1)错误代码
stack_size EQU 0x200
vector_size EQU 0x400
data_size EQU 0X400
; define stack
AREA mystack, DATA, READWRITE
stack_start
SPACE stack_size
stack_end
PRESERVE8
;define vectors
AREA RESET, DATA, READONLY
vectors
DCD stack_end ;stack-top
DCD code_start ;begin code
SPACE vector_size
vectors_end
IMPORT flower
;define data
AREA mydata, DATA, READWRITE
data_s
SPACE data_size
;define code
AREA mycode, CODE, READONLY,ALIGN=3
code_start PROC
MOV R0,#0 ;initial
MOV R1,#100
LDR R2,=data_s
B .
ENDP
loop_s
PUSH {R1-R12,LR}
CMP R1,#1000
BGE loop_end
BL flower
CMP R0,#0
STRNE R0,[R2]
ADDNE R2,R2,#4
ADD R1,R1,#1
B loop_s
loop_end
POP {R1-R12,PC}
ENDP
END
(2)正确代码
stack_size EQU 0x200
vector_size EQU 0x400
data_size EQU 0X400
; define stack
AREA mystack, DATA, READWRITE
stack_start
SPACE stack_size
stack_end
PRESERVE8
;define vectors
AREA RESET, DATA, READONLY
vectors
DCD stack_end ;stack-top
DCD code_start ;begin code
SPACE vector_size
vectors_end
IMPORT flower
;define data
AREA mydata, DATA, READWRITE
data_s
SPACE data_size
;define code
AREA mycode, CODE, READONLY,ALIGN=3
code_start PROC
MOV R0,#0 ;initial
MOV R8,#100
LDR R9,=data_s
loop_s
CMP R8,#1000
BGE loop_end
MOV R0,R8
BL flower
CMP R0,#1
STREQ R8,[R9]
ADDEQ R9,R9,#4
ADD R8,R8,#1
B loop_s
loop_end
B .
ENDP
END
(3)测试
浙公网安备 33010602011771号