嵌入式汇编实验三
环境:ADS
软件:Metrowerks CodeWarrior for ARM Developer Suite v1.2
注意:汇编文件.s的名称不能和c文件.c的名称相同,因为他们需要生成各自的.o文件。
一、交换字符串
要求:用C语言和汇编语言混合编程实现:在C语言程序中调用汇编语言代码,完成字符串STR1与STR2内容的互换(假设STR1和STR2长度一致)。
C语言:
# include <stdio.h>
extern void swap(char *d,char *s);
int main() {
char *str1 = "AAAAA";
char *str2 = "BBBBB";
printf("Before swaping:\n");
printf("%s\n%s\n", str1, str2);
swap(str1, str2);
printf("After swaping:\n");
printf("%s\n%s\n", str1, str2);
return(0);
}
汇编语言:
AREA Swap,CODE,READONLY
EXPORT swap
swap
LDRB R2,[R0]
LDRB R3,[R1]
STRB R2,[R1]
STRB R3,[R0]
ADD R0,R0,#1
ADD R1,R1,#1
CMP R2,#0
BNE swap
MOV PC,LR
END
二、排序
要求:用C语言和汇编语言混合编程实现:在C语言程序中调用汇编语言代码,将输入的20个字节数据,从大到小加以排序,大数在前,小数在后。
C语言:
# include <stdio.h>
extern void rank(char *s);
int main() {
char *str = "ABCDEFGHIJKLMNOPQRST";
printf("Before ranking:\n");
printf("%s\n", str);
rank(str);
printf("After ranking:\n");
printf("%s\n", str);
return(0);
}
汇编语言:
AREA Rank,CODE,READONLY
EXPORT rank
rank ; 冒泡排序
MOV R1,#19 ; R1:外层循环次数
loop1 ; 外循环
MOV R0,R4
MOV R2,#19 ; R2:内层循环次数
loop2 ; 内循环
LDRB R3,[R0],#1
LDRB R5,[R0]
MOV R6,PC ; 保存PC地址
ADD R6,R6,#8
CMP R3,R5
BLO swap
SUB R2,R2,#1
CMP R2,#0
BNE loop2
SUB R1,R1,#1
CMP R1,#0
BNE loop1
MOV PC,LR
swap
MOV R7,R3
MOV R3,R5
MOV R5,R7
STRB R3,[R0,#-1]
STRB R5,[R0]
MOV PC,R6
END
假设 MOV R6,PC 这条指令的地址是0x00008000,执行此条语句后 R6 的值会变为 0x00008008 ,因为对于3级流水线,PC总是指向下两条指令的地址,因此PC保存的值是当前指令地址值加8;对于5级流水线,PC保存的是当前指令地址加12
C程序在调用汇编程序时,选用 R0~R3 进行传参,R4~R7 用作记录 R0~R3 的初始地址,以保证 R0~R3 的值改变后能正常返回,所以此题中用了 R0 传递字符串,R4 记录的 R0 的一开始的地址,不能去修改它,所以不用 R4。
三、访问全局变量
要求:用C语言和汇编语言混合编程实现:用汇编语言完成对C语言全局变量的访问。假设CVAR1和CVAR2是C语言中定义的全局变量,请用一段汇编语言访问它们,完成两者的相加运算,结果存放在CVAR1中。
C语言:
# include <stdio.h>
extern void test3();
unsigned int CVAR1 = 1;
unsigned int CVAR2 = 5;
int main() {
printf("Before adding:\n");
printf("%d\n", CVAR1);
test3();
printf("After adding:\n");
printf("%d\n", CVAR1);
return(0);
}
汇编语言:
AREA Test3,CODE,READONLY
EXPORT test3
IMPORT CVAR1
IMPORT CVAR2
test3
LDR R0,=CVAR1
LDR R1,=CVAR2
LDR R2,[R0]
LDR R3,[R1]
ADD R2,R2,R3
STR R2,[R0]
MOV PC,LR
END
四、函数调用
要求:用C语言和汇编语言混合编程实现:利用汇编语言程序调用C语言子程序的方式来求 i+ 2i + 3i +4i + 5i +6*i的和(设i为一个整型常数)。
C语言:
# include <stdio.h>
extern int g(int a, int b, int c, int d, int e, int f) {
return a+b+c+d+e+f;
}
汇编语言:
AREA f,CODE,READONLY
EXPORT f
IMPORT g
ENTRY
start
MOV R0,#1 ;i的值
ADD R1,R0,R0 ;计算i*2
ADD R2,R1,R0 ;计算i*3
ADD R3,R1,R2 ;计算i*5
STR R3,[SP,#-4]!
ADD R3,R2,R2 ;计算i*6
STR R3,[SP,#-4]!
ADD R3,R1,R1 ;计算i*4
BL g
END
本题中需要传递 6 个参数,R0~R3 不够用,于是将多出来的 i * 5 和 i * 6 压入堆栈中,假设 SP 堆栈指针的初始值为 0x00000000,压入 i * 5 后,地址 0xFFFFFFFC 的值为 i * 5,SP 的值为 0xFFFFFFFC,接着压入 i * 6,SP 的值变为 0xFFFFFFF8,地址中的值为 i * 6
在调用函数的时候,R0~R3 分别传入 a~d 变量中,堆栈的传参是从小地址开始,先把地址为0xFFFFFFF8中的 i * 6 传入变量 d ,然后把地址 0xFFFFFFFC 中的 i * 5 传入变量 e