以前曾经使用GNU的 arm-linux-* 工具链在命令行模式下写过ARM的代码,前段时间安装了Keil的mdk-arm 开发工具,心血来潮想试试在命令行下能不能开发ARM,结果成功了。我所测试的代码非常简单,只是一个实验,具有实用价值的代码没有测试过。当然,如果有了图形界面的IDE再使用命令行开发,是多此一举、舍近求远了,这只是个人爱好吧。我的环境:windows7旗舰版;Keil arm-mdk V4.2;Cygwin(已经安好了make等基本工具)模拟开发的器件是arm最近推出的cortex-m4(带DSP处理单元).整个工程只包含4个文件:启动文件head.s、C文件main.c、分散加载文件start.sct、Makefile。下面是各个文件的内容。head.s 1 IMPORT main 2 AREA startup,CODE 3 THUMB 4 DCD 0x20000000 5 DCD reset 6 reset PROC 7 ENTRY 8 ; CPACR is located at address 0xE000ED88 9 LDR.W R0, =0xE000ED88 10 ; Read CPACR 11 LDR R1, [R0] 12 ; Set bits 20-23 to enable CP10 and CP11 coprocessors 13 ORR R1, R1, #(0xF 14 ; Write back the modified value to the CPACR 15 STR R1, [R0] 16 push {r0-r1} 17 LDR R0,=main 18 BL main 19 B . 20 ENDP 21 ALIGN 22 END其中的第8-15行是开启FPU处理单元的代码(针对有FPU的处理器),第16行用来测试堆栈的情况;第6行和第20行的PROC、ENDP告诉编译器这是个执行程序段(以便编译器在编译时把跳转地址的bit 0变为单数,例如第5行变成reset所在的地址+1,这是因为cortex-m4只支持thumb代码,在向thumb代码跳转时PC地址bit0必须为1)。main.c 1 int main() 2 { 3 float a=3.14159; 4 float b=2.987; 5 float c; 6 c=a*b*b; 7 return (int)c; 8 }这里使用了浮点运算,以测试是否能正确编译浮点运算为FPU的硬件指令。start.sct1 ROMLOAD 0x0 0x4000 2 { 3 EXEC_RO 0x0 4 { 5 head.o(startup, +first) 6 *(+RO) 7 8 } 9 RAM 0x1FFF8000 10 { 11 *(+RW,+ZI) 12 } 13 }分散加载文件,把启动代码放到最开始。Makefile1 main.bin:main.c head.s 2 armcc --cpu cortex-m4.fp -O0 --apcs=interwork --li -g -c -I "C:\Keil\ARM\CMSIS\Include" main.c -o main.o 3 armasm --cpu cortex-m4.fp --li --apcs=interwork -I "C:\Keil\ARM\CMSIS\Include" head.s -o head.o 4 armlink --cpu cortex-m4.fp --no_startup --libpath "C:\Keil\ARM\RV31\LIB" --scatter start.sct head.o main.o -o main.axf 5 fromelf --bin --output main.bin main.axf 6 fromelf main.axf -c|sed -n '/Section #1/,$$p'|sed '/Section #2/,$$d'>_main.list 7 #dos2unix _main.list 8 clean: 9 rm *.o *.axf *.list *.bin第4行这里有个--no_startup需要说明一下,在不添加这个选项时,Keil会“自作聪明”的在生成的汇编代码中添加一些代码,这些代码也许是我们并不想要的,所以增加这个--no_startup选项后就不再有这些代码了。第6行后面的sed是从调试信息中过滤出我们所需要看的部分,其它的被滤除。四个文件都具备后,在当前目录下执行make指令(会有两个警告信息,可以忽略),便可生成main.axf的调试映像了,可以在keil中调试;_main.list是生成的反汇编代码,内容如下:** Section #1 'EXEC_RO' (SHT_PROGBITS) [SHF_ALLOC + SHF_EXECINSTR] Size : 88 bytes (alignment 4) Address: 0x00000000 $d startup 0x00000000: 20000000 ...DCD 536870912 0x00000004: 00000009 ....DCD 9 $t $v0 reset 0x00000008: f8df0014 ....LDR.W r0,[pc,#20] ; [0x20] = 0xe000ed88 0x0000000c: 6801 .hLDR r1,[r0,#0] 0x0000000e: f4410170 A.p. ORR r1,r1,#0xf00000 0x00000012: 6001 .`STR r1,[r0,#0] 0x00000014: b403 ..PUSH {r0,r1} 0x00000016: 4803 .HLDR r0,[pc,#12] ; [0x24] = 0x29 0x00000018: f000f806 ....BL main ; 0x28 0x0000001c: e7fe ..B 0x1c ; reset + 20 $d 0x0000001e: 0000 ..DCW 0 0x00000020: e000ed88 ....DCD 3758157192 0x00000024: 00000029 )...DCD 41 $t .text main 0x00000028: eddf1a09 .... VLDR s3,[pc,#36] ; [0x50] = 0x40490fd0 0x0000002c: eef00a61 ..a. VMOV.F32 s1,s3 0x00000030: eddf1a08 .... VLDR s3,[pc,#32] ; [0x54] = 0x403f2b02 0x00000034: eeb00a61 ..a. VMOV.F32 s0,s3 0x00000038: ee601a80 `... VMUL.F32 s3,s1,s0 0x0000003c: ee611a80 a... VMUL.F32 s3,s3,s0 0x00000040: eeb01a61 ..a. VMOV.F32 s2,s3 0x00000044: eefd1ac1 .... VCVT.S32.F32 s3,s2 0x00000048: ee110a90 .... VMOV r0,s3 0x0000004c: 4770 pGBX lr $d 0x0000004e: 0000 ..DCW 0 0x00000050: 40490fd0 ..I@ DCD 1078530000 0x00000054: 403f2b02 .+?@ DCD 1077881602 09-03 20:54