學習 Linux 系統啟動流程,必須熟悉幾個匯編指令,總結給大家。
這里不是最全的,只列出一些最常用的匯編指令。
一.數據處理指令
1.數據傳送指令
【MOV指令】
把一個寄存器的值(立即數)賦給另一個寄存器,或者將一個常量賦給寄存器。
MOV指令的格式為:
MOV 目的寄存器,源操作數MOV R1,R0 ;將寄存器R0的值傳送到寄存器R1
2.算術運算指令
(1)【加法指令】:ADD
ADD 目的寄存器,操作數1,操作數2
ADD指令用于把兩個操作數相加,并將結果存放到目的寄存器中。
ADD R0,R1,R2 ;R0 = R1 + R2
ADD R0,R1,#256 ;R0 = R1 + 256
(2)【帶進位的加法指令】:ADC
ADC 目的寄存器,操作數1,操作數2
ADC指令用于把兩個操作數相加,再加上CPSR中的C條件標志位的值,并將結果存放到目的寄存器中。
(3)【減法指令】:SUB
SUB 目的寄存器,操作數1,操作數2
把操作數1減去操作數2,并將結果存放到目的寄存器中。
SUB R0,R1,R2 ;R0 = R1 - R2
SUB R0,R1,#256 ;R0 = R1 - 256
3.比較指令
(1)【直接比較指令】:CMP
CMP 操作數1,操作數2CMP R1,R0;將寄存器R1的值與寄存器R0的值相減,并根據結果設置CPSR的標志位
CMP R1,#100;將寄存器R1的值與立即數100相減,并根據結果設置CPSR的標志位
4.邏輯運算指令
(1)【邏輯與指令】:AND
AND 目的寄存器,操作數1,操作數2
AND 指令用于在兩個操作數上進行邏輯與運算,并把結果放置到目的寄存器中。
AND R0,R0,#3 ; 該指令保持R0的0、1位,其余位清零。
(2)【邏輯或指令】:ORR
ORR 目的寄存器,操作數1,操作數2
ORR 指令用于在兩個操作數上進行邏輯或運算,并把結果放置到目的寄存器中。
ORR R0,R0,#3 ; 該指令設置R0的0、1位,其余位保持不變。
二.轉移指令
【跳轉指令】
B 跳轉指令
BL 帶返回的跳轉指令
BLX 帶返回和狀態切換的跳轉指令
BX 帶狀態切換的跳轉指令
三.程序狀態寄存器訪問指令
1、【MRS指令】
MRS 通用寄存器,程序狀態寄存器(CPSR或SPSR)MRS R0,CPSR ;傳送CPSR的內容到R0
MRS R0,SPSR ;傳送SPSR的內容到R0
2、【MSR指令】
MSR 程序狀態寄存器(CPSR或SPSR)_<域>,操作數MSR CPSR,R0 ;傳送R0的內容到CPSR
MSR SPSR,R0 ;傳送R0的內容到SPSR
?資料直通車:Linux內核源碼技術學習路線+視頻教程內核源碼
學習直通車:Linuxc/c++高級開發【直播公開課】
零聲白金VIP體驗卡:零聲白金VIP體驗卡(含基礎架構/高性能存儲/golang/QT/音視頻/Linux內核)
四.加載/存儲指令
ARM 微處理器支持加載/存儲指令用于在寄存器和存儲器之間傳送數據,加載指令用于將存儲器中的數據傳送到寄存器,存儲指令則完成相反的操作。
1、【LDR指令】
LDR 目的寄存器,<存儲器地址>
LDR指令用于從存儲器中將一個32位的字數據傳送到目的寄存器中。
LDR R0,[R1] ;將存儲器地址為R1的字數據讀入寄存器R0。
LDR R0,[R1,R2] ;將存儲器地址為R1+R2的字數據讀入寄存器R0。
LDR R0,[R1,#8] ;將存儲器地址為R1+8的字數據讀入寄存器R0。
LDR R0,[R1,R2] ! ;將存儲器地址為R1+R2的字數據讀入寄存器R0,并將新地址R1+R2寫入R1。
LDR R0,[R1,#8] ! ;將存儲器地址為R1+8的字數據讀入寄存器R0,并將新地址R1+8寫入R1。
LDRB 和 LDRH 指令大家可以百度。
2、【STR指令】
STR 源寄存器,<存儲器地址>
STR指令用于從源寄存器中將一個32位的字數據傳送到存儲器中。該指令在程序設計中比較常用,且尋址方式靈活多樣,使用方式可參考指令LDR。
STR R0,[R1],#8 ;將R0中的字數據寫入以R1為地址的存儲器中,并將新地址R1+8寫入R1。
STR R0,[R1,#8] ;將R0中的字數據寫入以R1+8為地址的存儲器中。
STRB 和 STRH指令大家可以百度。
五.異常產生指令
1、【SWI指令】
SWI 24位的立即數
SWI指令用于產生軟件中斷,以便用戶程序能調用操作系統的系統例程。
SWI 0x02 ;該指令調用操作系統編號位02的系統例程。
2、【BKPT指令】
BKPT 16位的立即數
BKPT指令產生軟件斷點中斷,可用于程序的調試。
六.偽代碼
1.【AREA】
一個匯編程序至少要包含一個段,當程序太長時,也可以將程序分為多個代碼段和數據段,因此在匯編程序的開頭,我們一般的語句會用到AREA。
AREA 段名 屬性 1 ,屬性 2 ,.... AREA Init ,CODE ,READONLY ;定義一個代碼段,段名為 Init ,屬性為只讀。
2、【ALIGN】
ALIGN { 表達式 { ,偏移量 }}
ALIGN?偽指令可通過添加填充字節的方式,使當前位置滿足一定的對其方式。其中,表達式的值用于指定對齊方式,可能的取值為2的冪,如?1?、2?、4?、8?、16?等。eg : xxx = ALIGN(4)
3、【CODE16、CODE32】
CODE16 (或 CODE32 )
CODE16?偽指令通知編譯器,其后的指令序列為?16?位的?Thumb?指令。
CODE32?偽指令通知編譯器,其后的指令序列為?32?位的?ARM?指令。
4、【ENTRY】
ENTRY ENTRY(stext)
很常見!!!ENTRY?偽指令用于指定匯編程序的入口點。在一個完整的匯編程序中至少要有一個?ENTRY?(也可以有多個,當有多個?ENTRY?時,程序的真正入口點由鏈接器指定),但在一個源文件里最多只能有一個?ENTRY?(可以沒有)。
5、【END】
END
END?偽指令用于通知編譯器已經到了源程序的結尾。
原文作者:一起學嵌入式