国产毛片a精品毛-国产毛片黄片-国产毛片久久国产-国产毛片久久精品-青娱乐极品在线-青娱乐精品

查看: 1176|回復(fù): 0
打印 上一主題 下一主題

IMX6ULL開發(fā)板 初識(shí)ARM匯編

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2020-6-15 11:27:07 | 只看該作者 |只看大圖 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
我們?cè)趯W(xué)習(xí) Linux 嵌入式開發(fā)的時(shí)候,了解 ARM 匯編是很有必要的,雖然我們使用匯編編寫代碼的情況很少,但是有些情況下我們需要簡(jiǎn)單編寫一些匯編程序來協(xié)助我們調(diào)試板子(因?yàn)槲覀兊?i.MX6 UL 終結(jié)者開發(fā)板使用的 cpu ARM Cortex-A7 架構(gòu)的,cpu 剛上電必須要運(yùn)行匯編代碼,來初始化 cpu 的一些內(nèi)部功能,然后設(shè)置好 C 語言的環(huán)境,才能運(yùn)行 C 語言),比如一塊板子焊接回來,我們燒寫鏡像沒有問題,但是燒寫完,串口沒有打印信息,不能正常啟動(dòng),這時(shí)我們應(yīng)該不能確定是軟件問題還是硬件問題,我們可以在匯編里面通過點(diǎn)燈(點(diǎn)亮板子上的 led)的方式來確定下 cpu 有沒有運(yùn)行,此時(shí)我們就要用到匯編,因?yàn)?C 語言還沒有被執(zhí)行。所以我們需要了解并掌握下 ARM 匯編。
81 .1  GNU 匯編語法 匯編語法
GNU 匯編語法適用于所有的架構(gòu),并不是 ARM 獨(dú)享的,GNU 匯編由一系列的語句組成,每行一條語句,
每條語句有三個(gè)可選部分,如下:
labelinstruction @ comment
label 即標(biāo)號(hào),表示地址位置,有些指令前面可能會(huì)有標(biāo)號(hào),這樣就可以通過這個(gè)標(biāo)號(hào)得到指令的地址,標(biāo)號(hào)也可以用來表示數(shù)據(jù)地址。注意 label 后面的“:”,任何以“:”結(jié)尾的標(biāo)識(shí)符都會(huì)被識(shí)別為一個(gè)標(biāo)號(hào)。
instruction 即指令,也就是匯編指令或偽指令。
@符號(hào),表示后面的是注釋,就跟 C 語言里面的“/*”和“*/”一樣,其實(shí)在 GNU 匯編文件中我們也可以
使用/*”和“*/”來注釋。
comment 就是注釋內(nèi)容。
比如下面的代碼:
sum:
MOVS R0, #0X5a @設(shè)置 R0=0X5a
上面代碼中add”就是標(biāo)號(hào),“MOVS R0, #0X5a”就是指令,后面的“@設(shè)置 R0=0X5a”就是注釋。( 注意 :ARM  匯編中的指令 、 偽指令 、 偽操作 、 寄存器等 , 都可以全部使用大寫 , 也可以全部使用小寫 , 但是不能大小寫混用)
我們也可以使用.section 偽操作來定義一個(gè)段名,匯編系統(tǒng)中預(yù)定義了一些段名,如下:
.text //代碼段
.bss //未初始化的數(shù)據(jù)段
.data //初始化的數(shù)據(jù)段
.rodata //只讀數(shù)據(jù)段
我們自己也可以使用.section 定義一個(gè)段,如下:
.section .test_section @定義一個(gè) test_setcion
我們知道在 C 語言中,程序的入口是 main 函數(shù),在匯編中程序的入口標(biāo)號(hào)是“_start”,下面的代碼就是使用_start 作為入口標(biāo)號(hào):
.global _start
_start:
ldr r0, =0x5a @r0=0x5a
上面代碼中.global 是偽操作,表示_start 是一個(gè)全局標(biāo)號(hào),類似 C 語言里面的全局變量,常見的偽操作有:
.byte //定義單字節(jié)數(shù)據(jù),比如.byte 0x5a
.short //定義雙字節(jié)數(shù)據(jù),比如.short 0x5a5a
.long //定義 4 字節(jié)數(shù)據(jù),比如.long 0x5a5a5a5a
.equ //賦值語句,格式為: .equ 變量名,表達(dá)式,比如.equ num, 0x5a,表
num=0x5a
.align //數(shù)據(jù)字節(jié)對(duì)齊,比如:.align 4 表示 4 字節(jié)對(duì)齊
.end //表示源文件結(jié)束
.global //定義一個(gè)全局符號(hào),格式為:.global symbol,比如:.global _start
上面這些是最常見的偽操作,GNU 匯編還有其他的偽操作,如果想更箱子的了解偽操作可以參考《ARM
Cortex-A(armV7)編程手冊(cè) V4.0》(光盤目錄:i.MX6UL 終結(jié)者光盤資料\10_其它參考資料)
GNU 匯編也支持函數(shù),格式如下:
.type fun_name, @function
fun_name:
#content
ret
.type 指令指定 fun_name 為其它匯編程序調(diào)用此函數(shù)時(shí)的地址
fun_name 也為函數(shù)名
@function 表示函數(shù)內(nèi)容開始
ret 指令表示函數(shù)結(jié)束,返回到父函數(shù)調(diào)用子函數(shù)處
定義函數(shù)的例子如下:
.type add_fun, @function
add_fun:
add %ebx, %ebx
movl %ebx, %eax
ret
8.2 ARM 匯編指令
下面我們來學(xué)習(xí)下 ARM 的常用匯編指令,這里我們參考了文檔《ARM ArchitectureReference Manual ARMv7-Aand ARMv7-R edition》(光盤目錄:i.MX6UL 終結(jié)者光盤資料\10_其它參考資料)。
8.2.1 MOV  指令
MOV 指令用于將數(shù)據(jù)從一個(gè)寄存器拷貝到另外一個(gè)寄存器,或者將一個(gè)立即數(shù)傳遞到寄存器里面,使用示例如下:
MOV R0R1 @將寄存器 R1 中的數(shù)據(jù)傳遞給 R0,即 R0=R1
MOV R0, #0X12 @將立即數(shù) 0X12 傳遞給 R0 寄存器,即 R0=0X12
8.2.2 MRS  指令
MRS 指令用于將特殊寄存器(CPSR SPSR)中的數(shù)據(jù)傳遞給通用寄存器,要讀取特殊寄存器的數(shù)據(jù)只能
使用 MRS 指令!使用示例如下:
MRS R0, CPSR @將特殊寄存器 CPSR 里面的數(shù)據(jù)傳遞給 R0,即 R0=CPSR
8.2.3 MSR  指令
MSR 指令和 MRS 剛好相反,MSR 指令用來將普通寄存器的數(shù)據(jù)傳遞給特殊寄存器,也就是寫特殊寄存器,寫
特殊寄存器只能使用 MSR,使用示例如下:
MSR CPSR, R0 @R0 中的數(shù)據(jù)復(fù)制到 CPSR 中,即 CPSR=R0
8.2.4 LDR  指令
LDR 指令用于從存儲(chǔ)器中將一個(gè) 32 位的字?jǐn)?shù)據(jù)傳送到目的寄存器中。該指令通常用于從存儲(chǔ)器中讀取32 位的字?jǐn)?shù)據(jù)到通用寄存器,然后對(duì)數(shù)據(jù)進(jìn)行處理。當(dāng)程序計(jì)數(shù)器 PC 作為目的寄存器時(shí),該指令從存儲(chǔ)器中讀取的字?jǐn)?shù)據(jù)被當(dāng)作目的地址,從而可以實(shí)現(xiàn)程序流程的跳轉(zhuǎn)。該指令在程序設(shè)計(jì)中比較常用,其尋址
方式靈活多樣。使用示例如下:
LDR R0,[R1] //將存儲(chǔ)器地址為 R1 的字?jǐn)?shù)據(jù)讀入寄存器 R0
LDR R0,[R1R2] //將存儲(chǔ)器地址為 R1+R2 的字?jǐn)?shù)據(jù)讀入寄存器 R0
LDR R0,[R1,#8] //將存儲(chǔ)器地址為 R1+8 的字?jǐn)?shù)據(jù)讀入寄存器 R0
LDR R0,[R1]R2 //將存儲(chǔ)器地址為 R1 的字?jǐn)?shù)據(jù)讀入寄存器 R0,幵將新地址 R1
R2 寫入 R1
8.2.5 STR  指令
STR 是將數(shù)據(jù)寫入到存儲(chǔ)器中,示例代碼如下:
STR R1, [R0] //R1 中的值寫入到 R0 中所保存的地址中
8.2.6  入棧,出棧指令
棧被定義為一種先進(jìn)后出的數(shù)據(jù)結(jié)構(gòu),即最后進(jìn)棧的元素將被最先彈出來.這很像許多人進(jìn)入一條窄得只能 容納一個(gè)人通過的小道,如果要從這條道往回退出來的話,那么最先退出來的人是最后一個(gè)進(jìn)入小道的人.所以棧具有后進(jìn)先出的性質(zhì)(LIFO)。我們使用 push 指令實(shí)現(xiàn)入棧,示例代碼如下:
PUSH {R0~R3, R12} @R0~R3 R12 壓棧
出棧指令使用 POP,示例代碼如下:
POP {R0~R3,R12} @在恢復(fù) R0~R3,R12
8.2.7  跳轉(zhuǎn)指令
跳轉(zhuǎn)指令用于實(shí)現(xiàn)程序流程的跳轉(zhuǎn),ARM 程序中有兩種方法可以實(shí)現(xiàn)程序流程的跳轉(zhuǎn):
1.  使用專門的跳轉(zhuǎn)指令(B B 、 BL 、 BX BLX
2. 器 直接向程序計(jì)數(shù)器 C PC  寫入跳轉(zhuǎn)地址值
一般我們常用專門跳轉(zhuǎn)指令實(shí)現(xiàn)程序的跳轉(zhuǎn),下面我們來看下跳轉(zhuǎn)指令的使用:
B 指令
B 指令是最簡(jiǎn)單的跳轉(zhuǎn)指令。一旦遇到一個(gè) B 指令,ARM 處理器將立即跳轉(zhuǎn)到給定的目標(biāo)地址,從那里繼續(xù)執(zhí)行。注意存儲(chǔ)在跳轉(zhuǎn)指令中的實(shí)際值是相對(duì)當(dāng)前 PC 值的一個(gè)偏移量,而不是一個(gè)絕對(duì)地址,它的值由匯編器來計(jì)算(參考尋址方式中的相對(duì)尋址)。它是 24 位有符號(hào)數(shù),左移兩位后有符號(hào)擴(kuò)展為 32 位,表示的有效偏移為 26 (前后 32MB 的地址空間)。以下指令:
B Label ;程序無條件跳轉(zhuǎn)到標(biāo)號(hào) Label 處執(zhí)行
BL 指令
跳轉(zhuǎn)之前,會(huì)在寄存器 R14 中保存 PC 的當(dāng)前內(nèi)容,因此,可以通過將 R14 的內(nèi)容重新加載到 PC 中,來返回到跳轉(zhuǎn)指令之后的那個(gè)指令處執(zhí)行。該指令是實(shí)現(xiàn)子程序調(diào)用的一個(gè)基本但常用的手段。以下指令:
BL Label ;當(dāng)程序無條件跳轉(zhuǎn)到標(biāo)號(hào) Label 處執(zhí)行時(shí),同時(shí)將當(dāng)前的 PC 值保存到 R14
BLX  指令
ARM 指令集跳轉(zhuǎn)到指令中所指定的目標(biāo)地址,并將處理器的工作狀態(tài)由 ARM 狀態(tài)切換到 Thumb 狀態(tài),該指令同時(shí)將 PC 的當(dāng)前內(nèi)容保存到寄存器 R14 中。因此,當(dāng)子程序使用 Thumb 指令集,而調(diào)用者使用 ARM 指令集時(shí),可以通過 BLX 指令實(shí)現(xiàn)子程序的調(diào)用和處理器工作狀態(tài)的切換。同時(shí),子程序的返回可以通過將寄存器 R14 值復(fù)制到 PC 中來完成。指令格式如下:
BLX 目標(biāo)地址
X BX  指令
跳轉(zhuǎn)到指令中所指定的目標(biāo)地址,目標(biāo)地址處的指令既可以是 ARM 指令,也可以是 Thum 指令,指令格式如下:
BX{條件} 目標(biāo)地址
8.2.8  邏輯運(yùn)算指令
常用的邏輯運(yùn)算符如下:
AND a, b //a = a & b 按位與
AND a, b, #c //a = b & #c 按位與
AND a, b, c //a = b & c 按位與
ORR a, b //a = a | b 按位或
ORR a, b, #c //a = b | #c 按位或
ORR a, b, c //a = b | c 按位或
BIC a, b //a = a & (~b) 位清除
BIC a, b, #c //a = b & (~#c) 位清除
BIC a, b, c //a = b & (~c) 位清除
ORN a, b //a = a | (b) 按位或非
ORN a, b, #c //a = b |(#c) 按位或非
ORN a, b, c //a = b |(c) 按位或非
EOR a, b //a = a ^b 按位異或
EOR a, b, #c //a = b ^ #c 按位異或
EOR a, b, c //a = b ^ c 按位異或
8.2.9  算數(shù)運(yùn)算符
ADD, a, #b // a = a + #b 加法運(yùn)算
ADD a, b, c //a = b + c 加法運(yùn)算
ADD a, b, #c //a = b + #c 加法運(yùn)算
SUB a, #b //a = a - #b 減法運(yùn)算
SUB a, b, c //a = b - c 減法運(yùn)算
SUB a, b, #c //a = b - #c 減法運(yùn)算
MUL a, b, c //a = b * c 懲罰運(yùn)行算(32 位)
UDIV a, b, c //a = b/c 無符號(hào)除法
SDIV a, b, c //a = b/c 有符號(hào)除法
本節(jié)主要講解了一些最常用的指令,還有很多不常用的指令沒有講解,但是夠我們后續(xù)學(xué)習(xí)用了。要想詳細(xì)的學(xué)習(xí) ARM 的所有指令請(qǐng)參考《 ARM ArchitectureReference Manual ARMv7-A and ARMv7-Redition.pdf》和《ARM Cortex-A(armV7)編程手冊(cè) V4.0.pdf》這兩份文檔,他們分別在光盤資料的目錄:i.MX6UL 終結(jié)者光盤資料\10_其它參考資料。

本版積分規(guī)則

關(guān)于我們  -  服務(wù)條款  -  使用指南  -  站點(diǎn)地圖  -  友情鏈接  -  聯(lián)系我們
電子工程網(wǎng) © 版權(quán)所有   京ICP備16069177號(hào) | 京公網(wǎng)安備11010502021702
快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 香蕉在线视频播放 | 特级毛片永久久免费观看 | 欧美国产日韩1区俺去了 | 日本亚洲欧美在线 | 大焦伊人 | 亚洲 欧美 日韩 丝袜 另类 | 亚洲最大色网 | 日韩在线视频精品 | 一级毛片q片 | 香港黄页亚洲一级 | 日韩国产精品欧美一区二区 | 岛国视频在线观看免费播放 | 五月婷婷爱 | 色爽视频| 国产欧美一区二区三区精品 | 操穴网站| 日韩在线a视频免费播放 | 经典三级一区二区三区视频 | 在线精品免费视频 | 四虎免费永久网站入口 | 亚州三级视频 | 四虎国产成人亚洲精品 | 欧美性精品hd在线观看 | 在线性视频 | 亚洲一区在线免费观看 | 国产高清在线精品一区在线 | 一区二区三区视频观看 | 国产福利一区二区麻豆 | 中文字幕日韩欧美一区二区三区 | 欧美日韩精品一区二区另类 | 久久99精品麻豆国产 | 欧美日韩乱妇高清免费 | 免费色视频网站 | 99re视频精品 | 精品视频免费 | 国产一级特黄aa大片高清 | 亚洲天堂精品在线观看 | 桃色综合网 | 四虎成人免费大片在线 | 国产乱人伦精品一区二区 | 在线免费观看黄 |