以前曾經(jīng)使用GNU的 arm-linux-* 工具鏈在命令行模式下寫過ARM的代碼,前段時(shí)間安裝了Keil的mdk-arm 開發(fā)工具,心血來潮想試試在命令行下能不能開發(fā)ARM,結(jié)果成功了。我所測(cè)試的代碼非常簡(jiǎn)單,只是一個(gè)實(shí)驗(yàn),具有實(shí)用價(jià)值的代碼沒有測(cè)試過。 當(dāng)然,如果有了圖形界面的IDE再使用命令行開發(fā),是多此一舉、舍近求遠(yuǎn)了,這只是個(gè)人愛好吧。 我的環(huán)境: windows7旗艦版;Keil arm-mdk V4.2;Cygwin(已經(jīng)安好了make等基本工具) 模擬開發(fā)的器件是arm最近推出的cortex-m4(帶DSP處理單元).
整個(gè)工程只包含4個(gè)文件:?jiǎn)?dòng)文件head.s、C文件main.c、分散加載文件start.sct、Makefile。下面是各個(gè)文件的內(nèi)容。
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 << 20)
- 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處理單元的代碼(針對(duì)有FPU的處理器),第16行用來測(cè)試堆棧的情況;第6行和第20行的PROC、ENDP告訴編譯器這是個(gè)執(zhí)行程序段(以便編譯器在編譯時(shí)把跳轉(zhuǎn)地址的bit 0變?yōu)閱螖?shù),例如第5行變成reset所在的地址+1,這是因?yàn)閏ortex-m4只支持thumb代碼,在向thumb代碼跳轉(zhuǎn)時(shí)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 }
這里使用了浮點(diǎn)運(yùn)算,以測(cè)試是否能正確編譯浮點(diǎn)運(yùn)算為FPU的硬件指令。
start.sct - 1 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 }
分散加載文件,把啟動(dòng)代碼放到最開始。
Makefile - 1 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行這里有個(gè)--no_startup需要說明一下,在不添加這個(gè)選項(xiàng)時(shí),Keil會(huì)“自作聰明”的在生成的匯編代碼中添加一些代碼,這些代碼也許是我們并不想要的,所以增加這個(gè)--no_startup選項(xiàng)后就不再有這些代碼了。第6行后面的sed是從調(diào)試信息中過濾出我們所需要看的部分,其它的被濾除。
四個(gè)文件都具備后,在當(dāng)前目錄下執(zhí)行make指令(會(huì)有兩個(gè)警告信息,可以忽略),便可生成main.axf的調(diào)試映像了,可以在keil中調(diào)試;_main.list是生成的反匯編代碼,內(nèi)容如下: - ** 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 .h LDR r1,[r0,#0]
- 0x0000000e: f4410170 A.p. ORR r1,r1,#0xf00000
- 0x00000012: 6001 .` STR r1,[r0,#0]
- 0x00000014: b403 .. PUSH {r0,r1}
- 0x00000016: 4803 .H LDR 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 pG BX lr
- $d
- 0x0000004e: 0000 .. DCW 0
- 0x00000050: 40490fd0 ..I@ DCD 1078530000
- 0x00000054: 403f2b02 .+?@ DCD 1077881602
|