使用匯編的原因很簡單,就是匯編代碼的高效。在機器啟動的時候,利用匯編的高效,對硬件進行初始化,為加載內核,提供條件。
目前常用的ARM匯編指令有兩種:
*ARM標準匯編:適用于ARM公司的匯編器,適合在Windows平臺下使用。
*GNU匯編:使用與GNU交叉編譯工具鏈中的匯編器,適合于Linux平臺開發。
3.匯編程序框架:注意下面的操作環境是Redhat 6.4 + eclipse C/C++ +CDT插件。
匯編代碼的基本框架
匯編用到的地方,啟動代碼,效率要求高效的地方。
上面是啟動代碼的框架。
下面搭建框架:
start.S:
.text
.global _start
_start:
mov r2,#2
mov r3,#3
Makefile:
all : start.o
arm-linux-ld -Tgboot.lds -o start.elf $^
%.o : %.S
arm-linux-gcc -g -o $@ $^ -c
clean:
rm *.o *.elf
簡單工程的運行的結構:
鏈接器腳本:
Gboot.lds:
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS {
. = 0x50008000;
. = ALIGN(4);
.text :
{
start.o (.text)
*(.text)
}
. = ALIGN(4);
.data :
{
*(.data)
}
. = ALIGN(4);
bss_start = .;
.bss :
{
*(.bss)
}
bss_end = .;
}
運行的結果:
接下來是匯編代碼的操作實現:
mov r1,#6
mov r2,r1
mov r3,#10
@mvn:傳值取反的值
mvn r0,#4 @r0:4取反變為-5
mvn r1,#0b111000
mvn r2,r1 @r2:0b111000
Sub的實例:
Add的實例:
當然,我們也可以在執行的時候指定參數的值:如下圖,我們指定了r0=44,r2=66.
運行了之后:
And的實例;
Bic的實例:第三個數是源碼,源碼位為1的,對應的位清0,源碼位是0的,對應的位不變。
從上面的執行結果看到,r1的最高位,和最低兩位的1,對應源碼位的值都是1,所以,被清0,中間四位,對應源碼的四個0,保持不變1010.所以最后輸出了0b101000.
比較指令
Cmp指令的操作:比較的結果不會保持,回去影響cpsr對應的位:N或Z位。
我們可以看到r1-1=1是正數,cpsr的最高位四位2=0010,N,Z位都是0.
這里r1-3=-1,cpsr的最高四位8=1000,即是N位被置為1,表示結果是負數。
這里r1-2=0,cpsr的次高位被置為1,表示兩個數相等。
Txt指令的操作:測試位、按位與,結果為0 ,Z位被置為1,結果不為0,Z位置為0
按位與之后的值不為0,所以cpsr的Z位不會被置為1.
按位與之后的結果是為0的,所以cpsr的Z位被置1.結果高四位的值是4.
跳轉指令:
B指令:
上面的例子中,gt表示大于的時候跳轉,6>5所以跳轉到標簽branch1處執行。不會執行add r3,r1,r2.
上面,跳轉的條件不成立,順序執行,不跳轉。但是會順序執行,所以加個b end跳轉到end,執行空操作。
Bl:帶鏈接的跳轉:
Lr:
反匯編的代碼:
由上面看到lr保存的是bl返回來后的下一條地址,把他賦值給pc指針進行跳轉。
移位指令:
Lsl左移指令:
11左移兩位:1100
ror循環右移:
循環右移,最低位的1,被循環移動到了最高位。
程序狀態字訪問指令。
在GNU匯編中,我們不允許上面的 指令來操作訪問我們的程序字狀態寄存器指令,所以我們需要將他們的值移出,再進行操作訪問,修改等,操作完還要移進去。所以就設計到兩個指令:MSR和MRS指令。搬出mrs,搬回去msr。
執行了之后:
最后:
我們就是得通過上面的操作來改變cpsr里的值的。
存儲器訪問指令:
上面的都是核里面的指令,內存是通過存儲器訪問質指令。
Ldr指令:內存保存到寄存器
Str指令:寄存器保存到內存。
我們把r1設置成了開發板內存的地址,如上圖,接下來在memory里創建一個監控的地址:
接下來看看運行了上面的指令后的變化:如下圖,我們的0xff已經被保存到了0x50008000.
下面是ldr:
R2的值就是存進r0里的值,被取出來了。
這個匯編操作的工程代碼:
.text
.global _start
_start:
@ldr和str的操作
mov r0,#0xff
str r0,[r1]
ldr r2,[r1]
@程序狀態字寄存器訪問
mrs r0,cpsr
orr r0,#0b100
msr cpsr,r0
@ror:循環右移
mov r1,#0b11
mov r1,r1,ror#1
@lsl:左移
mov r1,#0b11
mov r1,r1,lsl#2
@bl指令:帶鏈接跳轉
bl func1
@b指令:
mov r1,#6
mov r2,#7
cmp r1,r2
bgt branch1@gt表示大于的時候跳轉
add r3,r1,r2
b end
func1:
mov r1,#23
mov pc,lr@函數的返回,固定格式。
branch1:
sub r3,r1,r2
end:
nop
@tst指令:
mov r1,#0b101
tst r1,#0b01
mov r1,#0b101
tst r1,#0b10
@cmp指令的操作:
mov r1,#2
cmp r1,#1
mov r1,#2
cmp r1,#3
mov r1,#2
cmp r1,#2
@bic:位清除指令
mov r1,#0b1101011
bic r2,r1,#0b1000011
@and的用法:邏輯與
mov r1,#5
and r2,r1,#0
mov r1,#5
and r2,r1,#1
@add:加法:
add r1,r0,r2
@sub:減法,注意被減數不能是立即數
mov r2,#4
sub r0,r2,#2
mov r1,#3
sub r3,r1,r0
@這是注釋,mov指令
mov r1,#6
mov r2,r1
mov r3,#10
@mvn:傳值取反的值
mvn r0,#4 @r0:4取反變為-5
mvn r1,#0b111000
mvn r2,r1 @r2:0b111000
上一篇:12.ARM偽指令操作
下一篇:10.ARM匯編的學習
- 熱門資源推薦
- 熱門放大器推薦
設計資源 培訓 開發板 精華推薦
- LTC2975 的典型應用 - 具有準確輸入電流和能量測量功能的 4 通道 PMBU 電源系統管理器
- STM32 Nucleo-64 開發板,帶 STM32WB15CC,支持 Arduino、ST Morpho 連接
- 使用 Analog Devices 的 LT1302CN8-5 的參考設計
- MC33364臨界導通模式反激轉換器的典型應用電路
- AD9754-EB,用于 AD9754、14 位、125 MSPS 高性能 D/A 轉換器的評估板
- LTC1064-3,優于用于數據通信的貝塞爾線性相位濾波器
- NCS2001SN2T1G 0.9V單電源運放正電容乘法器典型應用電路
- AM6TW-4803DH35Z ±3.3V 6 瓦雙路輸出 DC/DC 轉換器的典型應用
- 使用 Analog Devices 的 LTC1538IG-AUX 的參考設計
- DC1198B-B,使用 LTM4607EV、6 至 36 Vin 至 12V、5A 高效降壓-升壓 DC/DC 模塊穩壓器的演示板