sp,lr,pc即組合語言中幾個常見暫存器的使用

2021-07-02 06:14:25 字數 3424 閱讀 8380

arm彙編基礎**)

先看個例子:

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指向棧裡面的lr

ldmia   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;再壓fp

ldmia   sp,       //和s***b成對使用,

//fp=sp,sp=sp+4;先彈fp

//sp=sp,sp=sp+4;先彈sp,此處的彈出不會影響sp,因為ldmia是乙個機器週期執行完的。

//pc=sp,sp=sp+4;先彈pc

ldrh          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 中存放的值在退出被呼叫函式時必須與進入時的值相同。

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 要麼是零,要麼指向回溯結構的最當前的部分。

組合語言中的常數

1,數值常數 二進位制數 10110100b 八進位制數146q,5430 十進位制數146d,543 十六進製制數 1a2fh,0ff00h 實數12.48e 2,1a3c0000r 彙編時,則有匯程式設計序將所有的數值常數都轉換成二進位制標示的目標 凡是以字母a f開頭的十六進製制數,唏噓在前面...

組合語言中ASSUME簡介

size large url 組合語言中的assume偽指令 directive assume偽指令通知匯程式設計序為 段 資料段 附加段以及堆疊段選擇什麼名字。沒有assume偽指令時,匯程式設計序假設不分段,並自動把段超越字首用於所有定址儲存器資料的偽指令。assume語句只能用於完整的段定義。...

組合語言中xor指令 計算機組合語言

組合語言 雖然用機器語言編寫程式有很高的要求和許多不便,但編寫出來的程式執 行效率高,cpu嚴格按照程式設計師的要求去做,沒有多餘的額外操作。所以,在保留 程式執行效率高 的前提下,人們就開始著手研究一種能大大改善 程式可讀性的程式設計方法。為了改善機器指令的可讀性,選用了一些能反映機器指令功能的單...