GNU的匯編器是GNU Tools的一部分,可以用來ARM的匯編語言源代碼編譯為二進(jìn)制文件.關(guān)于GNU匯編器的介紹可以搜索《GNU Assembler Manual》.這里我們只是做一個簡短的介紹,對GNU匯編器有一個大概的認(rèn)識,同時通過兩個例子了解一下GNU ARM匯編.
? ? ?給出一個模板文件:
?
[cpp]?view plaincopyprint?
????.text???????????????????????????????????????????????;?Executable?code?follows??_start:?.global?_start??????????????????????????????????;?"_start"?is?required?by?the?linker??????.global?main????????????????????????????????????????;?"main"?is?our?main?program??????b?main??????????????????????????????????????????????;?Start?running?the?main?program??main:???????????????????????????????????????????????????;?Entry?to?the?function?"main"??;?Insert?your?code?here??????mov?pc,lr???????????????????????????????????????????;?Return?to?the?caller??????.end?? ? ? ? 匯編器的使用:
?
? ? ? 一種匯編器是arm-elf-as,一種是arm-linux-as之類的,這兩種匯編器是有細(xì)微區(qū)別.但是一般做開發(fā),半導(dǎo)體廠商都會提供特定的編譯器,用那個編譯器應(yīng)該是沒錯的,而且優(yōu)化效果應(yīng)該是最優(yōu)的,畢竟是芯片公司提供的嘛.他們對體系架構(gòu)最了解,很清楚的知道怎么去優(yōu)化.而我們一般的開發(fā)者也可以了解處理器的體系架構(gòu)和嵌入式系統(tǒng)的系統(tǒng)的特征來對匯編代碼和c代碼做優(yōu)化.
? ? ? 編譯過程:
? ? ? arm-elf-as -marm7tdmi --gdwarf2 -o filename.o filename.s
? ? ? -marm7tdmi是指定CPU,arm7tdmi是屬于ARMv4T的,一般來說同是ARMv4T應(yīng)該是兼容的.
? ? ? --gdwarf2是表示包含debug信息.
? ? ? 鏈接過程:
? ? ? arm-elf-ld -o filename.elf filename.o
? ? ? 和UNIX系統(tǒng)編程一樣,我們可以根據(jù)上面的步驟寫makefile,然后make一下.
? ? ? 具體ARM的指令集,偽指令就不寫了,資料很多.
? ? ? 下面舉兩個ARM匯編的實(shí)例,一個是裸機(jī)下的蜂鳴器(簡單的控制GPIO而已,比流水燈還簡單),一個是ARM linux下的"hello world"(利用系統(tǒng)調(diào)用來實(shí)現(xiàn)的).
? ? ? ?蜂鳴器的例子如下:
? ? ? ?beep.lds ?beep.S ?Makefile ?start.S
? ? ? start.S:
?
[cpp]?view plaincopyprint?
.text??.global?_start??_start:??????ldr?????r3,?=0x53000000?????@?WATCHDOG寄存器地址??????mov?????r4,?#0x0???????????????????????????str???r4,?[r3]??????????????@?寫入0,禁止WATCHDOG,否則CPU會不斷重啟????????ldr?????sp,?=1024*2?????????@?設(shè)置堆棧,注意:不能大于4k,?因?yàn)楝F(xiàn)在可用的內(nèi)存只有4K??????????????????????????????????????????@?nand?flash中的代碼在復(fù)位后會移到內(nèi)部ram中,此ram只有4K??????bl??????_main????????????????@?跳轉(zhuǎn)到main函數(shù)??halt_loop:??????b???????halt_loop??
? ? ? beep.S
?
?
[cpp]?view plaincopyprint?
.equ????GPBCON,???0x56000010????.equ????GPBDAT,???0x56000014??????.global?_main????_main:???????ldr?r0,=GPBCON????????ldr?r1,=0x1??????str?r1,?[r0]??loop:????????ldr?r2,=GPBDAT??????ldr?r1,=0x1??????str?r1,[r2]??????bl?delay????????ldr?r2,=GPBDAT??????ldr?r1,=0x0??????str?r1,[r2]??????bl?delay????????b?loop????delay:??????ldr?r3,=0x4ffffff????delay1:??????sub?r3,r3,#1????????cmp?r3,#0x0????????bne?delay1????????mov?pc,lr??.end??
? ? ? beep.lds
[cpp]?view plaincopyprint?
OUTPUT_FORMAT("elf32-littlearm",?"elf32-littlearm",?"elf32-littlearm")??OUTPUT_ARCH(arm)??ENTRY(_start)????SECTIONS{??????.?=?0x33000000;??????.text?:?{??????????*(.text)??????????*(.rodata)??????}????????.data?ALIGN(4):?{??????????*(.data)??????}????????.bss?ALIGN(4):?{??????????*(.bss)??????}??}??
? ? ? ?makefile:
?
?
[cpp]?view plaincopyprint?
CROSS?=??arm-linux-??CFLAGS?=?-nostdlib????beep.bin:?start.S?beep.S??????${CROSS}gcc?$(CFLAGS)?-c?-o?start.o?start.S??????${CROSS}gcc?$(CFLAGS)?-c?-o?beep.o?beep.S??????${CROSS}ld?-Tbeep.lds?start.o?beep.o?-o?beep.elf??????${CROSS}objcopy?-O?binary?-S?beep.elf?beep.bin??????rm?-f??*.o??????clean:??????rm?-f?*.elf?*.o??????rm?-f?beep.bin??
? ? ? ? 編譯后將beep.bin文件燒寫到dram中,就可以聽到聲音了.雖然可以運(yùn)行了,但還是有兩個疑問:
?
? ? ? ? 1.lds編譯鏈接文件的寫法和技巧 ? ?//后續(xù)要繼續(xù)追
? ? ? ? 2.elf文件的格式 ? ? ? ?//elf格式是比較新的可執(zhí)行文件格式,目前在很多OS上都是用這種格式.這個格式可以在有操作系統(tǒng)的情況下直接運(yùn)行,但是對于裸機(jī)的情況,必須對elf文件 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?做objcopy處理 ? ? ? ?后續(xù)也要繼續(xù)追
?
? ? ? ? hello world的例子如下:
? ? ? ? helloworld.S:
?
[cpp]?view plaincopyprint?
.data??????msg:??.asciz??"hello,?world\n"????.text?????????.align??2?????????.global?_start??_start:?????????ldr?????r1,?=msg?????????@?address?????????mov?????r0,?#1??????????@?stdout?????????mov?????r2,?#13?????????@?length?????????swi?????#0x900004???????@?sys_write?????????mov?????r0,?#0?????????swi?????#0x900001???????@?sys_exit?????????.align??2??
? ? ? ?makefile:
?
?
[cpp]?view plaincopyprint?
all:??????arm-linux-as?helloworld.S?-o?helloworld.o??????arm-linux-ld??helloworld.o?-o?helloworld??
? ? ? ? 將elf文件放到跑有l(wèi)inux的arm板子中,運(yùn)行就輸出hello world.也可以在ubuntu中qemu-arm helloworld模擬.
?
? ? ? ? 對比x86下同樣用系統(tǒng)調(diào)用來輸出hello world的程序:
?
[cpp]?view plaincopyprint?
.data??????msg:?.string?"hello\n"??????len?=?.?-?msg??.text??.global?_start????_start:??????nop??????movl?$len,?%edx??????movl?$msg,?%ecx??????movl?$1,?%ebx??????movl?$4,?%eax??????int?$0x80????????movl?$0,?%ebx??????movl?$1,?%eax??????int?$0x80??
? ? ? ? ? ?它們有幾點(diǎn)不同:
?
? ? ? ? ? ? 1.arm是用swi指令來進(jìn)行軟中斷,陷入內(nèi)核態(tài)來實(shí)現(xiàn)系統(tǒng)調(diào)用的.而x86是用int $0x80
? ? ? ? ? ? 2.x86的系統(tǒng)調(diào)用號是用eax寄存器表示的,是第一個參數(shù).而arm的swi直接帶有系統(tǒng)調(diào)用號,0x900004是0x900000+4,其中0x900000是base.
?
? ? ? ? ? ? 根據(jù)google,做了上面的總結(jié),對GNU ARM匯編有了認(rèn)識,并且對系統(tǒng)調(diào)用軟中斷,中斷處理,uboot異常向量表等等有了探究的欲望,也對elf格式和編譯鏈接有了興趣,根據(jù)自己的方向和精力,后續(xù)對這些內(nèi)容做一個或深或淺的學(xué)習(xí).
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?轉(zhuǎn)載于:blog.csdn.net/dndxhej
轉(zhuǎn)載于:https://www.cnblogs.com/Daniel-G/archive/2012/10/15/2725057.html
總結(jié)
以上是生活随笔為你收集整理的GNU ARM汇编--(二)汇编编译链接与运行的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。