前言
最近在學習Cortex-A的linux編程,拿到的是《原子嵌入式Linux驅動開發說解》,文中說到,如果想要學習好Uboot和Linux內核,就必須要學會匯編。
GNU匯編語法
我們在使用過的STM32中的MDK與IAR下啟動文件startup_stmp32f10x_hd.s中的匯編語法是有所不同的,所以不用將MDK下的匯編文件直接復制到IAR下去編譯,這是因為MDK和IAR的編譯器不同,因此匯編語法就有一些區別,ARM匯編使用的是GCC交叉編譯器,所以匯編代碼要符合GNU語法。
GNU匯編語法適用于所有的架構,并不是ARM獨享的,GNU匯編由一系列的語句組成,每行一條語句,每條語句有3個可選部分,解釋如下:
label:instruction @ comment
Lable : 即標號,表示地址位置,有些指令前面可能會有標號,這樣就可以通這個標號得到指令的地址,標號也可以用來表數據地址,注意label后面的“:",任何以":"結尾的標識符者會被識別為一個標號。
instruction : 即指令,也就是匯編指令的偽指令。
@符號:表示后面的是注釋,就跟C語言中的”/ “和” /“一樣的,其實在GNU匯編文件中我們也可以使用"/ "和" /”來注釋。
comment :就是注釋內容。
代碼如下所示
add:
MOVS R0, #0x123 @設置 R0=0x123
上面的代碼中"add:”就是標號,“MOVS R0,#0x123"就是指令,最后的"@設置 R0=0x123"就是注釋。
注意:ARM中的指令,偽指令、偽操作、寄存器名等可以全部使用大寫,也可以全部使用小寫,但是不能大小寫混用。
用戶可以使用.section偽操作來定義一個段,匯編系統預定義一些段名,解釋如下:
.tex :表示代碼段。
.data :初始化的數據段。
.bss :未初始化的數據段。
.rodata :只讀數據段。
我們當然可以使用.section來定義一個段,每個段以段名開始,以下一段名或者文件結尾結束。代碼如下:
.section .testsection @定義一個testsection段
匯編程序的黙認入口標號是_start,不過我們可以在鏈接腳本中使用ENTRY來指明其他的入口點,下面的代碼就是使用_start作為入口標號。
.gloabl _start
_start:
ldr r0, =0x12 @ 給r0移入0x123.
上面代碼中,global是偽操作,表示_start 是一個全局標號,類似C語言中的全局變量一樣,下面為常見的偽操作。
.byte :定義單字節數據,比如.byte 0x123。
.short :定義雙字節數據,比如.short 0x1234。
.long :定義一個4字節數據,比如.long 0x12345678。
.equ :賦值語句,格式為.equ變量名,表達式如.equ num,0x123 表示num = 0x123。
.align :數據字節對齊,如.align 4 表示4字節對齊。
.end :表示源文件結束。
.global :定義一個全局符號,格式為.global sysmbol,比如 .global _start。
GNU匯編還有其他的偽操作,最常見的如上所示。如果想詳細地了解全部的偽操作,可以參考《ARM Cortex-A(armV7)編程手冊V4.0》中的相關內容。
GNU匯編同樣也支持函數,函數格式如下:
函數名:
函數體
返回語句
GNU匯編函數返回語句不是必需要的,以下示例就是匯編寫的Cortex-A7中斷服務函數:
/* 未定義中斷 */
Undef ined_Handler:
ldr r0, = Undefined_Handler
bx r0
/* SVC 中斷 */
ldr r0, = SVC_Handler
bx r0
/* 預取終止中斷 */
ldr r0, = PrefAbort_Handler
bx r0
上述代碼中定義了3個匯編函數:Unddefined_Handler、SVC_Handler和PrefAbort_Handler。以Undefined_Handler函數為來看匯編函數組成,"Undefined_Handler“就是函數名,"ldr r0, = Undefined_Handler”是函數體,“bx r0"是函數返回語句,"bx"指令是返回指令,函數返回語句不是秘需的。
-
嵌入式
+關注
關注
5082文章
19104瀏覽量
304809 -
Linux
+關注
關注
87文章
11292瀏覽量
209328 -
GNU
+關注
關注
0文章
143瀏覽量
17492 -
Cortex-A
+關注
關注
0文章
20瀏覽量
34266 -
匯編語法
+關注
關注
0文章
2瀏覽量
2096
發布評論請先 登錄
相關推薦
評論