对很多人来说,学习C语言时的第一个程序是Hello World 。那么在学习ARM汇编语言的起始阶段,如何写出一个hello world程序呢?
由于ARM汇编语言程序不像通常的C语言程序,没有操作系统环境,不能做为常见的可执行程序在操作系统上运行,也不能方便地通过标准输出设备来显示字符串。所以在ARM汇编语言中实现hello world比C语言中要麻烦不少。目前网上对这一个话题做较比完整分析的文章还很少见,因此通过一个具体的例子来说明一下。
选择的工具是MDKl μVision4。首先新建一个project。项目名称随意,在选择目标设备时可以选择ARM/Cortex-M3
新建一个主文件main.s ,主要代码如下:
PRESERVE8
AREA example,CODE,READONLY ; 声明代码段example
IMPORT ||Lib$$Request$$armlib||
IMPORT printf
EXPORT main
;汇编代码调用printf的例子
main
STMFD sp!,{r4,lr}
ADR r0,arg0
BL printf
LDMFD sp!,{r4,pc}
; 为了arg0的地址4字节对齐,特地跳过两个字节
skip
DCB "\0\0"
arg0
DCB "hello world\n\0"
END
如果仅仅只有这个主文件,无法得到正确的结果,还需要重写一下fputc这个函数,将字符输出到MDK的调试窗口。
因此新建一个fputc.c文件,主要内容如下:
#include <string.h>
#include <stdio.h>
#define ITM_Port8(n) (*((volatile unsigned char *)(0xE0000000+4*n)))
#define ITM_Port16(n) (*((volatile unsigned short*)(0xE0000000+4*n)))
#define ITM_Port32(n) (*((volatile unsigned long *)(0xE0000000+4*n)))
#define DEMCR (*((volatile unsigned long *)(0xE000EDFC)))
#define TRCENA 0x01000000
struct __FILE { int handle; /* Add whatever needed */ };
FILE __stdout;
FILE __stdin;
int fputc(int ch, FILE *f) {
if (DEMCR & TRCENA) {
while (ITM_Port32(0) == 0);
ITM_Port8(0) = ch;
}
return(ch);
}
为了对芯片做一些初始化工作,还需要新建一个startup.s文件。是从MDK软件自带的例子中复制过来的。
此外,不能使用默认的内存段设置,所以做了一个小的scatter文件,内容如下:
LR_IROM1 0x00000000 0x00040000 { ; load region size_region
ER_IROM1 0x00000000 0x00040000 { ; load address = execution address
*.o (RESET, +First)
.ANY (+RO)
}
RW_IRAM1 0x20000000 0x00020000 { ; RW data
.ANY (+RW +ZI)
}
}
做好了这些准备工作,通过build操作,可以顺利生成结果文件。再点击调试按钮,调试界面如下图所示:
再点击run按钮,可以在右下方的调试窗口看到输出了hello world.
完整的例子项目可通过CSDN的资源下载获取。