日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

GNU ARM汇编--(二)汇编编译链接与运行

發(fā)布時(shí)間:2025/7/14 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 GNU ARM汇编--(二)汇编编译链接与运行 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

GNU的匯編器是GNU Tools的一部分,可以用來(lái)ARM的匯編語(yǔ)言源代碼編譯為二進(jìn)制文件.關(guān)于GNU匯編器的介紹可以搜索《GNU Assembler Manual》.這里我們只是做一個(gè)簡(jiǎn)短的介紹,對(duì)GNU匯編器有一個(gè)大概的認(rèn)識(shí),同時(shí)通過兩個(gè)例子了解一下GNU ARM匯編.

? ? ?給出一個(gè)模板文件:

?

[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)體廠商都會(huì)提供特定的編譯器,用那個(gè)編譯器應(yīng)該是沒錯(cuò)的,而且優(yōu)化效果應(yīng)該是最優(yōu)的,畢竟是芯片公司提供的嘛.他們對(duì)體系架構(gòu)最了解,很清楚的知道怎么去優(yōu)化.而我們一般的開發(fā)者也可以了解處理器的體系架構(gòu)和嵌入式系統(tǒng)的系統(tǒng)的特征來(lái)對(duì)匯編代碼和c代碼做優(yōu)化.

    ? ? ? 編譯過程:

    ? ? ? arm-elf-as -marm7tdmi --gdwarf2 -o filename.o filename.s

    ? ? ? -marm7tdmi是指定CPU,arm7tdmi是屬于ARMv4T的,一般來(lái)說(shuō)同是ARMv4T應(yīng)該是兼容的.

    ? ? ? --gdwarf2是表示包含debug信息.

    ? ? ? 鏈接過程:

    ? ? ? arm-elf-ld -o filename.elf filename.o

    ? ? ? 和UNIX系統(tǒng)編程一樣,我們可以根據(jù)上面的步驟寫makefile,然后make一下.

    ? ? ? 具體ARM的指令集,偽指令就不寫了,資料很多.

    ? ? ? 下面舉兩個(gè)ARM匯編的實(shí)例,一個(gè)是裸機(jī)下的蜂鳴器(簡(jiǎn)單的控制GPIO而已,比流水燈還簡(jiǎn)單),一個(gè)是ARM linux下的"hello world"(利用系統(tǒng)調(diào)用來(lái)實(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會(huì)不斷重啟??
  • ??
  • ????ldr?????sp,?=1024*2?????????@?設(shè)置堆棧,注意:不能大于4k,?因?yàn)楝F(xiàn)在可用的內(nèi)存只有4K??
  • ????????????????????????????????????????@?nand?flash中的代碼在復(fù)位后會(huì)移到內(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)行了,但還是有兩個(gè)疑問:

    ?

    ? ? ? ? 1.lds編譯鏈接文件的寫法和技巧 ? ?//后續(xù)要繼續(xù)追

    ? ? ? ? 2.elf文件的格式 ? ? ? ?//elf格式是比較新的可執(zhí)行文件格式,目前在很多OS上都是用這種格式.這個(gè)格式可以在有操作系統(tǒng)的情況下直接運(yùn)行,但是對(duì)于裸機(jī)的情況,必須對(duì)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模擬.

    ?

    ? ? ? ? 對(duì)比x86下同樣用系統(tǒng)調(diào)用來(lái)輸出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指令來(lái)進(jìn)行軟中斷,陷入內(nèi)核態(tài)來(lái)實(shí)現(xiàn)系統(tǒng)調(diào)用的.而x86是用int $0x80

    ? ? ? ? ? ? 2.x86的系統(tǒng)調(diào)用號(hào)是用eax寄存器表示的,是第一個(gè)參數(shù).而arm的swi直接帶有系統(tǒng)調(diào)用號(hào),0x900004是0x900000+4,其中0x900000是base.

    ?

    ? ? ? ? ? ? 根據(jù)google,做了上面的總結(jié),對(duì)GNU ARM匯編有了認(rèn)識(shí),并且對(duì)系統(tǒng)調(diào)用軟中斷,中斷處理,uboot異常向量表等等有了探究的欲望,也對(duì)elf格式和編譯鏈接有了興趣,根據(jù)自己的方向和精力,后續(xù)對(duì)這些內(nèi)容做一個(gè)或深或淺的學(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汇编--(二)汇编编译链接与运行的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。