先看個例子:
void test2(int a,int b,int c)
gcc反彙編:
00000064 :
mov ip, sp //ip=sp;儲存
sp新手
s***b sp!, //先對sp減
4,再對fp,
ip,lr,
pc壓棧。
---------1
sub fp, ip, #4 ; 0x4 //fp=ip-4;此時
fp指向棧裡面的「fp」
sub sp, sp, #24 ; 0x18 //分配空間
str r0, [fp, #-28] //
str r1, [fp, #-32] //
str r2, [fp, #-36] //引數壓棧
ldr r3, [fp, #-28] //
str r3, [fp, #-24] //
ldr r3, [fp, #-32] //
str r3, [fp, #-20] //
ldr r3, [fp, #-36] //
str r3, [fp, #-16] //
sub sp, fp, #12 ; 0xc //sp=fp-12;此時
sp指向棧裡面的
lrldmia sp, //彈棧
pc=lr
,sp=ip
,fp=fp
。然後位址加
4---------1
彙編基礎:
s***b sp!, //sp=sp-4,sp=pc;先壓
pc//sp=sp-4,sp=lr;再壓
lr//sp=sp-4,sp=ip;再壓
ip//sp=sp-4,sp=fp;再壓
fpldmia sp, //和
s***b
成對使用,
//fp=sp,sp=sp+4;先彈
fp//sp=sp,sp=sp+4;先彈
sp,此處的彈出不會影響
sp,因為
ldmia
是乙個機器週期執行完的。
//pc=sp,sp=sp+4;先彈
pcldrh r0, [r13, #0xc] //載入無符號半字資料,即低16位
ldrb r0, [r13, #0x4] //載入一位元組資料,即低8位。
注意:r11=fp;r12=ip;r13=sp
;r14=lr
;r15=pc
;r0,r1,r2
用於傳遞引數和存放函式返回值。
注意;低位址的暫存器被壓入低位址記憶體中,也就是說如果向下增長,高位址暫存器先壓,向上增長測試低位址先壓。
注意:根據「arm-thumb
過程呼叫標準」:
1, r0-r3
用作傳入函式引數,傳出函式返回值。在子程式呼叫之間,可以將
r0-r3
用於任何用途。被呼叫函式在返回之前不必恢復
r0-r3
。---
如果呼叫函式需要再次使用
r0-r3
的內容,則它必須保留這些內容。
2, r4-r11
被用來存放函式的區域性變數。如果被呼叫函式使用了這些暫存器,它在返回之前必須恢復這些暫存器的值。
3, r12
是內部呼叫暫時暫存器
ip。它在過程鏈結膠合**(例如,互動操作膠合**)中用於此角色。在過程呼叫之間,可以將它用於任何用途。被呼叫函式在返回之前不必恢復
r12。
4,暫存器
r13
是棧指標
sp。它不能用於任何其它用途。
sp 中存放的值在退出被呼叫函式時必須與進入時的值相同。
5,暫存器
r14
是鏈結暫存器
lr。如果您儲存了返回位址,則可以在呼叫之間將
r14
用於其它用途,程式返回時要恢復
6,暫存器
r15
是程式計數器
pc。它不能用於任何其它用途。
7,在中斷程式中,所有的暫存器都必須保護,編譯器會自動保護r4~
r11,所以一般你自己只要在程式的開頭
sub lr,lr,#4
stmfd sp!,;保護r0~
r3,r12,lr
就可以了,除非你用彙編人為的去改變
r4~r11
的值。(具體去看
ucos os_cpu_a.s
中的irq
中斷的**)
補充:暫存器名字
reg # apcs 意義
r0 a1 工作暫存器
r1 a2 "
r2 a3 "
r3 a4 "
r4 v1 必須保護
r5 v2 "
r6 v3 "
r7 v4 "
r8 v5 "
r9 v6 "
r10 sl 棧限制
r11 fp 楨指標
r12 ip
r13 sp 棧指標
r14 lr 連線暫存器
r15 pc 程式計數器
回溯結構
暫存器 fp (
楨指標)
應當是零或者是指向棧回溯結構的列表中的最後乙個結構,提供了一種追溯程式的方式,來反向跟蹤呼叫的函式。
回溯結構是:
位址高階
儲存**指標
[fp] fp
指向這裡
返回 lr 值
[fp, #-4]
返回 sp 值
[fp, #-8]
返回 fp 值
[fp, #-12]
指向下乙個結構
[儲存的
sl]
[儲存的
v6]
[儲存的
v5]
[儲存的
v4]
[儲存的
v3]
[儲存的
v2]
[儲存的
v1]
[儲存的
a4]
[儲存的
a3]
[儲存的
a2]
[儲存的
a1]
[儲存的
f7]
三個字
[儲存的
f6]
三個字
[儲存的
f5]
三個字
[儲存的
f4]
三個字
pc 總是包含下乙個要被執行的指令的位置。
lr (總是
)包含著退出時要裝載到
pc 中的值。在
26-bit
位**中它還包含著
psr。
sp 指向當前的棧塊
(chunk)
限制,或它的上面。這是用於複製臨時資料、暫存器和類似的東西到其中的地方。在
risc os
下,你有可選擇的至少
256
位元組來擴充套件它。
fp 要麼是零,要麼指向回溯結構的最當前的部分。
ARM彙編基礎
簡介 在armv6中,simd指令使用位 19 16 作為結果的單個位元組或半字的大於或等於 ge 標誌。您可以使用這些標誌來控制以後的sel指令,有關詳細資訊,請參閱第a4 127頁的sel 設定規則有以下三種 指令為半字操作 根據上半字計算的結果,將ge 3 2 設定或清除 根據下半字計算的結果...
ARM彙編程式設計基礎之四 ARM彙編偽操作
掌握了基本的arm彙編指令後,要寫出簡單的arm匯程式設計序,還必須要掌握基本的arm彙編偽操作 directive 現在我們來看乙個簡單的匯程式設計序,該程式呼叫子程式完成了加法操作。1 檔名 test.s 2 功能 實現兩個暫存器相加 3 area example,code,readonly 宣...
ARM彙編程式設計基礎之四 ARM彙編偽操作
掌握了基本的arm彙編指令後,要寫出簡單的arm匯程式設計序,還必須要掌握基本的arm彙編偽操作 directive 現在我們來看乙個簡單的匯程式設計序,該程式呼叫子程式完成了加法操作。1 檔名 test.s 2 功能 實現兩個暫存器相加 3 area example,code,readonly 宣...