ARM彙編中^、!、cxsf符號和movs等指令使用

2020-12-14 電子產品世界

.macro restore_user_regs
ldr r1,[sp, #S_PSR]
ldr lr,[sp, #S_PC]! @ !用來控制基址變址尋址的最終新地址是否進行回寫操作,
@執行ldr之後sp被回寫成sp+#S_PC基址變址尋址的新地址
msrspsr,r1 @把cpsr的值保存到spsr中
ldmdb sp,{r0 - lr}^ @lr=[sp-1*4],r13=[sp-2*4],r12=[sp-3*4],......,r0=[sp-15*4]
@因為沒對pc賦值,所以^的表示將數據恢復到User模式的[r0-lr]寄存器組中[gliethttp]
mov r0,r0
add sp,sp,#S_FRAME_SIZE - S_PC
movs pc,lr
.endm

本文引用地址:

http://www.eepw.com.cn/article/201611/318785.htm

其他指令正在學習中[隨時補充gliethttp]
-----------------------------
1.ldr ip,[sp],#4將sp中內容存入ip,之後sp=sp+4;
ldr ip,[sp,#4]將sp+4這個新地址下內容存入ip,之後sp值保持不變
ldr ip,[sp,#4]!將sp+4這個新地址下內容存入ip,之後sp=sp+4將新地址值賦給sp
str ip,[sp],#4將ip存入sp地址處,之後sp=sp+4;
str ip,[sp,#4]將ip存入sp+4這個新地址,之後sp值保持不變
str ip,[sp,#4]!將ip存入sp+4這個新地址,之後sp=sp+4將新地址值賦給sp
-----------------------------
2.movs r1,#3 ;movs將導致ALU被更改,因為r1賦值非0,即操作結果r0非0,所以ALU的Z標誌清0
bne 1f;因為Z=0,說明不等,所以向前跳到標號1:所在處繼續執行其他語句
-----------------------------
3.LDM表示裝載,STM表示存儲.
LDMED LDMIB預先增加裝載
LDMFD LDMIA過後增加裝載
LDMEA LDMDB預先減少裝載
LDMFA LDMDA過後減少裝載

STMFA STMIB預先增加存儲
STMEA STMIA過後增加存儲
STMFD STMDB預先減少存儲
STMED STMDA過後減少存儲

注意ED不同於IB;只對於預先減少裝是相同的.在存儲的時候,ED是過後減少的.
FD、ED、FA、和EA指定是滿棧還是空棧,是升序棧還是降序棧.
對於存儲STM而言
先加後存FA姑且這麼來記,先加(first add),存數據
後加先存EA姑且這麼來記,存數據,後加end add
先減後存FD姑且這麼來記,先減first dec,存數據
後減先存ED姑且這麼來記,存數據,後減end dec
然後記憶LDM,LDM是STM的反相彈出動作,所以
因為是先加後存,所以後減先取FA就成了與STM對應的取數據,後減
因為是後加先存,所以先減後取EA就成了與STM對應的先減,取數據
因為是先減後存,所以後加先取FD就成了與STM對應的取數據,後加
因為是後減先存,所以先加後取ED就成了與STM對應的先加,取數據
我想通過上面的變態方式可以比較容易的記住這套指令[gliethttp]
一個滿棧的棧指針指向上次寫的最後一個數據單元,而空棧的棧指針指向第一個空閒單元.
一個降序棧是在內存中反向增長(就是說,從應用程式空間結束處開始反向增長)而升序棧在內存中正向增長.
其他形式簡單的描述指令的行為,意思分別是
IA過後增加(Increment After)、
IB預先增加(Increment Before)、
DA過後減少(Decrement After)、
DB預先減少(Decrement Before).

RISC OS使用傳統的滿降序棧.在使用符合APCS規定的編譯器的時候,它通常把你的棧指針設置在應用程式空間的
結束處並接著使用一個FD(滿降序-Full Descending)棧.如果你與一個高級語言(BASIC或C)一起工作,你將別無選擇.
棧指針(傳統上是R13)指向一個滿降序棧.你必須繼續這個格式,或則建立並管理你自己的棧.
-----------------------------
4.
teq r1,#0 //r1-0,將結果送入狀態標誌,如果r1和0相減的結果為0,那麼ALU的Z置位,否則Z清0
bne reschedule//ne表示Z非0,即:不等,那麼執行reschedule函數
-----------------------------
5.使用tst來檢查是否設置了特定的位
tst r1,#0x80 //按位and操作,檢測r1的0x1<<7,即第7位是否置1,按位與之後結果為0,那麼ALU的Z置位
beq reset //如果Z置位,即:以上按位與操作結果是0,那麼跳轉到reset標號執行
-----------------------------
6.^的理解
^是一個後綴標誌,不能在User模式和Sys系統模式下使用該標誌.該標誌有兩個存在目的:
6.1.對於LDM操作,同時恢復的寄存器中含有pc(r15)寄存器,那麼指令執行的同時cpu自動將spsr拷貝到cpsr中
如:在IRQ中斷返回代碼中[如下為ads環境下的代碼gliethttp]
ldmfd {r4} //讀取sp中保存的的spsr值到r4中
msr spsr_cxsf,r4 //對spsr的所有控制為進行寫操作,將r4的值全部注入spsr
ldmfd {r0-r12,lr,pc}^//當指令執行完畢,pc跳轉之前,將spsr的值自動拷貝到cpsr中[gliethttp]
6.2.數據的送入、送出發生在User用戶模式下的寄存器,而非當前模式寄存器
如:ldmdb sp,{r0 - lr}^;表示sp棧中的數據到User分組寄存器r0-lr中,而不是恢復到當前模式寄存器r0-lr
當然對於User,System,IRQ,SVC,Abort,Undefined這6種模式來說[gliethttp]r0-r12是共用的,只是r13和r14
為分別獨有,對於FIQ模式,僅僅r0-r7是和前6中模式的r0-r7共用,r8-r14都是FIQ模式下專有.



-----------------------------
7.spsr_cxsf,cpsr_cxsf的理解
c-control field maskbyte(PSR[7:0])
x-extension field maskbyte(PSR[15:8])
s-status field maskbyte(PSR[23:16)
f-flags field maskbyte(PSR[31:24]).
老式聲明方式:cpsr_flg,cpsr_all在ADS中已經不在支持
cpsr_flg對應cpsr_f
cpsr_all對應cpsr_cxsf

需要使用專用指令對cpsr和spsr操作:mrs,msr
mrs tmp,cpsr //讀取CPSR的值
bic tmp,tmp,#0x80 //如果第7位為1,將其清0
msr cpsr_c,tmp //對控制位區psr[7:0]進行寫操作
-----------------------------
8.cpsr的理解
CPSR = Current Program Status Register
SPSR = Saved Program Status Registers
CPSR寄存器(和保存它的SPSR寄存器)



(上圖)
N,Z,C,V稱為ALU狀態標誌
N:如果結果是負數則置位
Z:如果結果是零則置位
C:如果發生進位則置位
V:如果發生溢出則置位
I:置位表示禁用IRQ中斷,清0表示使能IRQ
F:置位表示禁用FIQ中斷,清0表示使能FIQ
T:置位表示系統運行在Thumb態,清0表示運行在ARM態
M[4:0]:
10000 User模式,和System系統模式一樣
10001 FIQ模式
10010 IRQ模式
10011 SVC超級管理模式
10111 Abort數據異常模式
11011 Undefined未定義指令模式
11111 System系統模式,和User模式一樣

舉例:
ands r2,r2,#7使用運算結果改變標誌位,如果運算結果r2=0,那麼Z置位,EQ相等判斷成立
subs r2,r2,#1使用運算結果改變標誌位,如果運算結果r2=0,那麼Z置位,EQ相等判斷成立
beq wordcopy
-----------------------------
9.指令後綴和條件判斷



(上圖)
EQ :等於
NE :不等
CS :無符號>=
CC :無符號<
MI :負數
PL :非負[>=0]
VS :溢出
VC :無溢出
HI :無符號>
LS :無符號<=
GE :有符號>=
LT :有符號<
GT :有符號>
LE :有符號<=
AL :總是[默認]

對於arm彙編指令,可以參考linux內核的arch/arm目錄,那裡的彙編指令很豐富[gliethttp_20080603]
__CopyFromStart
; ldr r3, [r9],#4
; str r3, [r7], #4
; sub r8, r8, #4
ldrb r3, [r9], #1
strb r3, [r7], #1
sub r8, r8, #1
cmp r8, #0
bgt __CopyFromStart
b __JumpToBootImage

__JumpToBootImage
MOV pc, r0

相關焦點

  • 常用ARM彙編指令
    本文引用地址:http://www.eepw.com.cn/article/201611/322957.htmARM指令集可以分為六大類,分別為數據處理指令、Load/Store指令、跳轉指令、程序狀態寄存器處理指令、協處理器指令和異常產生指令。
  • ARM指令學習筆記
    >SHL R2,3ADD R1,R2就是說arm的指令更人性化,加上後來對arm偽指令的學習,我個人覺得arm指令集是彙編中的高級語言了。這個指令比較神奇,可以在程序首寫一些諸如ASSERTtop<>temp的斷言錯誤指令,在彙編編譯器對彙編程序的第二遍掃描中,如果其中ASSERT條件不成立,ASSERT偽指令將報告該錯誤信息,從而減少錯誤。有點像C++中try和catch。3.彙編控制偽指令/宏偽指令彙編控制偽指令用於條件彙編、宏定義、重複彙編控制等。
  • ARM彙編特殊符號 彙編符號引用
    特殊符號 ---- 對應指令 ---- 含義 ---- 示例^---- MAP----定義結構化內存表----MAP 4096;內存表首地址為4096#----FIELD----定義內存表中的數據,結合MAP指令使用----MAP 4096STACKSVC FIELD
  • ARM指令中特殊符號意義
    為location counter,可在源文件中指示當前地址。該符號可以被引用或賦值。ARM彙編程序中的符號在ARM彙編語言中,符號(symbols)可以代表地址(addresse)、變量(variables)和數字常量(numeric constants)。當符號代表地址時,又稱為標號(lable)。
  • Android逆向學習|對ARM指令的一次學習
    Intel和ARM兩大陣營還可以再細分。Intel的架構中x86代表32位cpu,x86_64代表64位的cpu,x86彙編語言學習最為普遍。ARM架構也有32位和64位之分。深入問題在《計算機組成原理》和《彙編語言》中,我們知道了計算機指令的組成一條指令(32位) = 操作碼(前16位):操作數(後16位)
  • ARM彙編和內嵌彙編
    反之如果立即數很大,超過了12bit的表示範疇,那麼就不能用一條mov指令了,畢竟arm指令最大只有32bit的空間可用(RISC的arm所有的指令長度是一致的,效率較高,當然我們並不關心16bit的thumb指令)。
  • 有關arm彙編中的align
    經常會看到arm-linux彙編中有如下的指令:.align n它的含義就是使得下面的代碼按一定規則對齊,.align n 指令的對齊值有兩種方案,n 或 2^n ,各種平臺最初的彙編器一般都不是gas,採取方案1或2的都很多,gas的目標是取代原來的彙編器,必然要保持和原來彙編器的兼容,因此在gas中如何解釋 .align指令會顯得有些混亂,原因在於保持兼容。
  • android平臺arm指令學習和調試
    */一、Ndk下內聯彙編跟vc下一樣,ndk編譯環境下也能使用內聯彙編,如下:本文引用地址:http://www.eepw.com.cn/article/201611/317575.htmincludeintmy_thumb(intdummy)
  • 基於Android的ARM彙編語言系列之五:ARM指令集與Thumb指令集
    章節列表之一:ARM彙編語言開篇之二:C/C++程序生成ARM彙編程序的過程分析之三:ARM彙編語言程序結構之四:ARM處理器的尋址方式之五
  • Android ARM 指令學習
    寄存器是處理特有的高速存儲部件,它們可以用來暫存指令,數據和位址,高級語言用到中用到的變量,常量,結構體,類等數據用到了ARM彙編語言中,就是使用寄存器保存的值或內存地址,寄存器的數據量有限,ARM微處理器共有37個32位寄存器,其中31個為通用寄存器,6個為狀態寄存器,ARM處理器器支持7中運行模式。1;用戶模式(usr)ARM 處理器正常的程序執行狀態。
  • 常用ARM指令集及彙編
    318760.htm(一)ARM指令集1.指令格式2.條件碼3.ARM存儲器訪問指令1)LDR/ STR-加載/ 存儲指令2)LDM/ STM-多寄存器加載/ 存儲指令3)SWP-寄存器和存儲器交換指令4.ARM數據處理指令1)數據傳送指令a)MOV-數據傳送指令
  • 彙編語言---乘法指令及符號擴展
    乘法指令的被乘數是隱含操作數,乘數需在指令中顯式寫出來。執行指令時,CPU會根據乘數是8位還是16位來自動選用被乘數是AL還是AX。格式及功能介紹無符號數乘法指令指令格式:MUL opr功能:將指令中指定的操作數與隱含的被乘數(都為無符號數)相乘,所得的乘積按表中的對應關係存放。
  • 哪幾種情況中必須使用內聯彙編或嵌入型彙編?
    ARM系列文章,請點擊以下匯總連結:《從0學arm合集》一、gcc 內聯彙編內聯彙編即在C中直接使用彙編語句進行編程,使程序可以在C程序中實現C語言不能完成的一些工作,例如,在下面幾種情況中必須使用內聯彙編或嵌入型彙編。
  • ARM彙編指令:.align理解和用法
    對齊偽指令ALIGN對齊偽指令格式:ALIGN Num其中:Num必須是2的冪,如:2、4、8和16等。偽指令的作用是:告訴彙編程序,本偽指令下面的內存變量必須從下一個能被Num整除的地址開始分配。如果下一個地址正好能被Num整除,那麼,該偽指令不起作用,否則,彙編程序將空出若干個字節,直到下一個地址能被Num整除為止。
  • ARM處理器寄存器和彙編指令系統
    、塊複製尋址和相對尋址2)條件執行幾乎所有的ARM指令都可以包含一個可選的條件碼,句法中以{cond}來標識。cond 就是上面所說的條件碼,因此指令可以變成LDREQ或STRNE類似的名稱,表示滿足某些條件時該條指令才會執行。B 可選後綴,表示傳送Rd的最低有效字節,就是所謂的無符號字節傳送,字節加載的時候是用0來擴展到32位的。T 可選後綴,即使處理器是在特權模式下,存儲系統也將訪問看成是處理器在用戶模式下。不能和前索引偏移一起使用。
  • 彙編語言的指令格式和基本語法講解
    ,而是在對源程序進行彙編連結時完成的.所以,語句中各表達式的值必須在彙編或連結時就是確定的,也就是說,表達式中各標識符的值在彙編或連結時就應該是確定的;3、標號:標號是由標識符表示的指令的名稱,用於指示對應指令的位置(地址);標號具有三個屬性:段地址、偏移地址和類型;標號的段地址和偏移地址屬性是指該標號所對應的指令所在段的段地址和段內偏移地址;
  • 單片機彙編指令入門學習和查看
    在進行彙編程序設計時,MSP430的指令系統是程序的主體,但為了方便程序編制,還定義了一些指令,這些指令不參與和影響程序的執行,也不在計算機中運行,這類指令稱為偽指令。一般彙編器偽指令能幫助用戶完成以下事情:·將代碼和數據彙編到規定的段中·在存儲器中用未初始化的變量保留空間·控制彙編後列表文件的格式·初始化存儲器·彙編條件塊·定義全局變量·規定彙編器可以從中獲得宏的庫
  • arm-linux-ld命令 ld連結腳本
    我們看它是如何編譯的,注意我們這裡使用的不是arm-linux-gcc而是arm-elf-gcc,二者之間沒有什麼比較大的區別,arm-linux-gcc可能包含更多的庫文件,在命令行的編譯上面是沒有區別。
  • 學習逆向工程(外掛)基礎:彙編指令總結
    逆向工程的過程也就是把軟體逆向分析成代碼的過程,代碼可以實彙編代碼也可能是原始碼。下面介紹兩種方法:反彙編,即使用反彙編器,把程序的原始機器碼,翻譯成較便於閱讀理解的彙編代碼。這適用於任何的電腦程式,對不熟悉機器碼的人特別有用。流行的相關工具有OllyDebug和IDA。
  • 51單片機彙編指令的記憶方法
    MCS-51使用彙編語言指令,它共有44個操作碼助記符,33種功能,其操作數有#data、direct、Rn、@Ri等。這裡先介紹指令助記符及其相關符號的記憶方法。一、助記符號的記憶方法1 表格列舉法把44個指令助記符按功能分為五類,每類列表記憶。此處從略,請讀者自己總結。