開始想的比較簡單,在開始配置uboot的時候開始看最開始的匯編,發現了之前用arm7當單片機用的時候沒有涉及到匯編這些東西,看到將arm指令相關基礎知識的時候感覺沒必要看,現在才發現這個是基本功,如果想進入嵌入式或者驅動開發,必須要了解芯片架構和指令系統,arm在arm7之後最主要的就是有了mmu功能,這個也是arm+linux的基本功。“基本功”,我師傅常說的一個詞,現在真的領會到了它的含義。做東西還是不能只了解表面的東西,尤其是嵌入式驅動方面一方面和軟件打交道,另外最重要的一點要理解硬件。這才是嵌入式軟件和通用軟件的最大區別。
下面開始學習下arm的尋址方式。這裡主要是參考《arm嵌入式程序設計》這本小冊子,講的arm的基礎知識,初學的同學們可以看看,和8086對比著講的,很不錯。
arm有一下的集中尋址方式:
1. 立即數尋址
這是一種比較簡單的尋址方式,操作數包含在指令當中。取出指令,即取出了操作數。對應的尋址方式也就叫做立即數尋址。
例:
;注意arm匯編中,指令不能頂格寫,在前面加空格。
;而定義變量的時候,必須頂格寫,這裡新手要注意。
ADD R0,R0,#1 ;R0 <==R0 +1 ,把R0的內容加1。
ADD R0,R0,#0x30 ;R0 <==R0 +0x30,把R0的內容加 0x30。
說明:以上兩條指令中,第二個源操作數 #1 和#0x30為立即數。立即數必須以#作為前綴,對於16進制的立即數,要求有"0x"或者"&"符號。
2. 寄存器尋址
將寄存器中的值作為操作數,這種方式即為寄存器尋址。此種方式較為各類微處理器常用,執行效率高。
例:
ADD R0,R1,R3 ;R0 <==R1+R3
將R1和R3的內容相加,結果存放到R0。
3. 寄存器移位尋址
其是將2 寄存器尋址做變化而得到的一種新的尋址方式。即移位,第二個操作數通過相應移位和第一個操作數運算後放到目的寄存器中。
例:
ADD R0,R1,R3,LSL #3 ;R0 <== R0+R3*8 ,R3的值左移3位就是乘以8,結果與R1的值相加,存放到R0.
ARM的移位(或者循環移位)操作有如下幾種:
LSL 邏輯左移,寄存器中低位空出的有效位用0填充
LSR 邏輯右移,寄存器中高端空出的有效位用0填充
ASR 算數右移,移位過程中必須保持符號位不變,即若源操作數為正,則高位用0填充,若為負,則高位用1填充。 其每移一位的操作和邏輯右移相同,僅是如果原最高位為1,則移位後最高位補1,所以在移大於1位時左邊的高位都是1.
即:
MOV R1,#0
MOV R2,#&80000000 ;此處立即數為負數,
MOV R1,R2,ASR #3
R1 內的值為 0xF0000000
若立即數換為0x40000000,則R1的值最後為0x08000000.
ROR 循環右移,一處的最低位移到空出的最高位
RRX 擴展的循環右移,操作數右移一位(每次執行只能移動1位),高端空出的位用進位標志位C的當前值來填充。
4.寄存器間接尋址
寄存器間接尋址,就是以寄存器中的值作為操作數的地址。這種尋址方式類似於c語言中取指針對應的變量的值 *p。
例:
ADD R0,R1,[R2] ;R0 《==R1 + [R2]
LDR R0,[R1] ;R0 <==[R1]
STR R0,[R1] ;[R1] <== R0
第一條指令為將R2的值作為操作數的地址,將此地址對應的位置的操作數和R1相加,存放到R0 ,[R2]類似於 取指針對應的值 *p。
第二條指令為將R1的值作為地址的寄存器中的數傳送到R0中。類似於c語言 R0 = *R1;
第三條指令將R0的值傳送到R1的值作為地址的寄存器中。 類似於c語言中 *R1 = R0;