最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

ARM匯編語言編程

2023-07-16 18:10 作者:dyldw  | 我要投稿

內(nèi)存參考視頻和知乎文章https://zhuanlan.zhihu.com/p/388683540

復(fù)制內(nèi)容到md編輯器應(yīng)該就可讀了。


> 點(diǎn)開頭的是偽指令,例如`.file` `.global`

> 冒號結(jié)尾的是標(biāo)簽,例如`main:`、`_start`

## 寄存器

在ARM64架構(gòu)下,CPU提供了33個寄存器, 其中前31個(0~30)是通用寄存器,最后2個(31,32)是專用寄存器(sp 寄存器和 pc 寄存器)

前面0~30個通用寄存器的訪問方式有2種:


- 當(dāng)將其作為 32bit 寄存器的時候,使用 W0 ~ W30 來引用它們。(數(shù)據(jù)保存在寄存器的低32位)

- 當(dāng)將其作為 64bit 寄存器的時候,使用 X0 ~ X30 來引用它們。

第31個專用寄存器的訪問方式有4種:


- 當(dāng)將其作為 32bit 棧幀指針寄存器(stack pointer) 的時候,使用 WSP 來引用它。

- 當(dāng)將其作為 64bit 棧幀指針寄存器(stack pointer) 的時候,使用 SP 來引用它。

- 當(dāng)將其作為 32bit 零寄存器( zero register )的時候,使用 WZR 來引用它。

- 當(dāng)將其作為 64bit 零寄存器( zero register )的時候,使用 ZR 來引用它。


另外需要注意的,像 FP (X29) ,LR(X30) 寄存器都不能和 SP(x31) 寄存器一樣用名字來訪問,而只能使用數(shù)字索引來訪問它們。

其實(shí)還有第32個專用寄存器,它就是 PC ( x32)寄存器,但是在ARM的匯編文檔里面說明了,你無法在匯編中使用 PC 名稱的方式或者用 X32 數(shù)字索引的訪問它,因?yàn)樗皇墙o匯編用的,而是給CPU執(zhí)行匯編指令時用的,它永遠(yuǎn)記錄著當(dāng)前CPU正在執(zhí)行哪一句指令的地址。

| 寄存器?????| 說明?????????????|

| -------------- | ---------------------------- |

| X0 寄存器???| 用來保存返回值(或傳參)???|

| X1 ~ X7 寄存器 | 用來保存函數(shù)的傳參??????|

| X8寄存器????| 也可以用來保存返回值?????|

| X9 ~ X28寄存器 | 一般寄存器,無特殊用途????|

| x29(FP)寄存器?| 用來保存棧底地址???????|

| X30 (LR)寄存器 | 用來保存返回地址???????|

| X31(SP) 寄存器 | 用來保存棧頂?shù)刂???????|

| X31(ZR)寄存器?| 零寄存器,恒為0???????|

| X32(PC)寄存器?| 用來保存當(dāng)前執(zhí)行的指令的地址 |


## 內(nèi)存布局

一個ARM64的進(jìn)行會擁有一個非常大的虛擬內(nèi)存映射空間,其中又分為兩大塊:


- 內(nèi)核地址(0xffff_ffff_ffff_ffff ~ 0xffff_0000_0000_0000范圍的256TB的尋址空間),

- 用戶地址 (0x0000_ffff_ffff_ffff ~ 0x0000000000000_0000范圍的256TB的尋址空間) 。

這里我們只關(guān)心用戶地址,其中有分為兩大塊:

- 棧內(nèi)存( Stack),從高位向低位生長。

- 堆內(nèi)存 ( Heap ), 從低位向高位生長。

其中我們知道棧內(nèi)存首先是按照線程為單元的,每個線程都有自己的棧內(nèi)存塊,然后每個線程的棧內(nèi)存又可以根據(jù)函數(shù)的調(diào)用層級關(guān)系分為不同的棧幀( Stack Frame )。

## 尋址模式

### 立即數(shù)尋址

將數(shù)據(jù)直接存放的指令中發(fā)給CPU,首先由于ARM的一條指令占了32bit,而操作碼本身也要占據(jù)一些位,所以留給立即數(shù)的位數(shù)肯定不到32bit,其次并不是滿足指定位數(shù)的數(shù)字都是立即數(shù),ARM中的立即數(shù)必須可以通過某個8bit的數(shù)據(jù)經(jīng)過循環(huán)右移得到。

```asm

ADD R0, R0, #1 ;R0 <- (R0 + #1)

MOV R7, #1 ;R7 <- #1

SWI 0

```

### 寄存器直接尋址

將寄存器中的數(shù)據(jù)用作操作數(shù)

```asm

MOV R0, R1 ;R0 <- R1

ADD R0, R1, R2 ;R0 <- (R1 + R2)

```


```asm

.global _start

_start:

LDR R0, =list;=list是list標(biāo)簽第一個元素的內(nèi)存地址,將這個內(nèi)存地址賦值給R0寄存器


.data

list:

.word 4, 5, -5, 1, 0, 2, -3

;以字為元素類型的列表

```

### 寄存器間接尋址

將寄存器中的數(shù)據(jù)作為主存中操作數(shù)的地址,去到相應(yīng)的主存地址取得操作數(shù),用`[R0]`表示將`R0`中的數(shù)據(jù)當(dāng)作操作數(shù)的地址,`[R0]!`表示將`R0`中的數(shù)據(jù)當(dāng)作操作數(shù)的地址并將操作后的結(jié)果地址給`R0`

```asm

LDR R0,[R1]????;將R1指向的數(shù)據(jù)加載到R0中?

STR R0, [R1]!????;將R0存儲的數(shù)據(jù)加載到R1指向的主存地址中,加載完畢R1中為操作后的地址

ADD R0,R1,[R2]

```


```asm

.global _start

_start:

LDR R0, =list;=list是list標(biāo)簽第一個元素的內(nèi)存地址,將這個內(nèi)存地址賦值給R0寄存器

LDR R1, [R0] ;將R0寄存器中數(shù)據(jù)作為內(nèi)存地址,從內(nèi)存中取數(shù)據(jù)賦值給R1

LDR R2, [R0, #4] ;將R0寄存器中數(shù)據(jù)加4作為內(nèi)存地址,從內(nèi)存中取數(shù)據(jù)賦值給R2(R0寄存器中數(shù)據(jù)不變)

LDR R2, [R0, #4]! ;將R0寄存器中數(shù)據(jù)加4作為內(nèi)存地址,從內(nèi)存中取數(shù)據(jù)賦值給R2。(R0寄存器中數(shù)據(jù)也加4),R2 = list[++i]

LDR R2, [R0], #4 ;將R0寄存器中數(shù)據(jù)作為內(nèi)存地址,從內(nèi)存中取數(shù)據(jù)賦值給R2。然后將R0寄存器中值加4, R2 = list[i++]

; LDR R2, [R0, #4]! 與 LDR R2, [R0], #4 的關(guān)系類似于++i與i++


.data

list:

.word 4, 5, -5, 1, 0, 2, -3

;以字為元素類型的列表

```


## 算術(shù)與CPSR標(biāo)志

```asm

.global _start

_start:

MOV R0, #5

MOV R1, #7

ADD R2, R0, R1 ; R2 = R0 + R1

ADDS R2, R0, R1

ADC R2, R0, R1

SUB R2, R0, R1 ; R2 = R0 - R1

SUBS R2, R0, R1 ; R2 = R0 - R1,設(shè)置CPSR

SUBS R2, R1, R0 ; R2 = R1 - R0,設(shè)置CPSR

MUL R2, R0, R1 ; R2 = R0 * R1?


.data

list:

.word 4, 5, -5, 1, 0, 2, -3

```


![當(dāng)R0(5)-R1(7)時R2所得結(jié)果](:/aceca647862c488dbc9f805ea283f38e)

![另一種R0-R1時R2所得結(jié)果](:/6ba6591acdbf4f9ba7f1ad80f369ecf5)

如圖可以看出,如何解釋寄存器中值是正數(shù)還是負(fù)數(shù)需要額外標(biāo)志位。cpsr寄存器就存儲這些標(biāo)志位。

`SUB`命令是不設(shè)置`CPSR`寄存器的,`SUBS`會設(shè)置`CPSR`寄存器。當(dāng)所得結(jié)果可能是負(fù)數(shù)時應(yīng)該使用`SUBS`。

## 邏輯運(yùn)算與移位

```asm

AND R2, R0, R1

ORR R2, R0, R1

EOR R2, R0, R1

MVN R0, R0

LSL ; 邏輯左移

LSR ; 邏輯右移

ROR ; ROR(循環(huán)右移)

```

`ROR`(循環(huán)右移指令把所有位都向右移,最低位復(fù)制到進(jìn)位標(biāo)志位和最高位。

![ROR循環(huán)右移圖示](:/2651b8a8f91e4805a98e00a84d09fed1)


```asm

MOV R0, #10

MOV R1, R0

LSL R1, #1

; 以上兩句等價于 MOV R1, R0, LSL #1

ROR R0, #1

```

## 條件與分支

假設(shè)現(xiàn)在AX寄存器中的數(shù)是0002H,BX寄存器中的數(shù)是0003H。

執(zhí)行的指令是:CMP?AX,?BX


??執(zhí)行這條指令時,先做用AX中的數(shù)減去BX中的數(shù)的減法運(yùn)算。

列出二進(jìn)制運(yùn)算式子:

![計(jì)算式子](:/d77016612485453786099a95338a63bb)

所以,運(yùn)算結(jié)果是 0FFFFH

根據(jù)這個結(jié)果,各標(biāo)志位將會被分別設(shè)置成以下值:

?????CF=1,因?yàn)橛薪栉?/p>

?????OF=0,未溢出

?????SF=1,結(jié)果是負(fù)數(shù)

?????ZF=0,結(jié)果不全是零

???還有AF, PF等也會相應(yīng)地被設(shè)置。CMP 比較指令做了減法運(yùn)算以后,根據(jù)運(yùn)算結(jié)果設(shè)置了各個標(biāo)志位。標(biāo)志位設(shè)置過以后,0FFFFH這個減法運(yùn)算的結(jié)果就沒用了,它被丟棄,不保存。執(zhí)行過了CMP指令以后,除了CF,ZF,OF, SF,等各個標(biāo)志位變化外,其它的數(shù)據(jù)不變。

### 控制流指令

```asm

cmp r0, #0

beq LABEL1 ; r0==0那么向前跳轉(zhuǎn)到LABEL1處執(zhí)行

bne LABEL2 ; 否則向后跳轉(zhuǎn)到LABEL2處執(zhí)行

```

無條件轉(zhuǎn)移指令:`BAL`


條件轉(zhuǎn)移指令

```asm

BEQ??相等

BNE??不等

BPL??非負(fù)

BMI??負(fù)

BCC??無進(jìn)位

BCS??有進(jìn)位

BLO??小于(無符號數(shù))

BHS??大于等于(無符號數(shù))

BHI??大于(無符號數(shù))

BLS??小于等于(無符號數(shù))

BVC??無溢出(有符號數(shù))

BVS??有溢出(有符號數(shù))

BGT??大于(有符號數(shù))

BGE??大于等于(有符號數(shù))

BLT??小于(有符號數(shù))

BLE??小于等于(有符號數(shù))

```


## 帶有分支的循環(huán)


```asm

.global _start

.equ endlist, 0xaaaaaaaa


_start:

LDR R0, =list

MOV R1, #0

LDR R2, =endlist

LDR R3, [R0]

ADD R1, R1, R3

loop:

LDR R3, [R0, #4]!

CMP R2, R3

BEQ exit

ADD R1, R1, R3

BAL loop

exit:


.data

list:

.word 1,2,3,4,5,6,7,8,9,10

```


## 條件指令執(zhí)行

```asm

CMP R0, R1

ADDLT R2, R2, #1 ;如果R0小于R1,那么將R2加1

;類似的有MOVEGE R2, #1

```


## 使用LR寄存器進(jìn)行分支并返回

```asm

.global _start

_start:

MOV R0, #1

MOV R1, #2

BL add2??;存儲下一個要執(zhí)行的指令的地址到lr寄存器,并跳轉(zhuǎn)到標(biāo)簽add2

MOV R3, #3


add2:

ADD R2, R0, R1

bx lr?;返回到lr保存的地址繼續(xù)執(zhí)行

```


## 從堆棧內(nèi)存中保存和檢索數(shù)據(jù)


```asm

.global _start

_start:

MOV R0, #1

MOV R1, #2

PUSH {R0, R1}

BL get_value

POP {R0, R1}

BAL exit


get_value:

MOV R0, #5

MOV R1, #7

ADD R2, R0, R1

BX lr


exit:

```

ARM匯編語言編程的評論 (共 條)

分享到微博請遵守國家法律
鹤庆县| 新昌县| 琼中| 磐安县| 永安市| 勃利县| 克什克腾旗| 陈巴尔虎旗| 吴桥县| 柞水县| 阆中市| 荆州市| 稻城县| 长沙市| 雅江县| 东安县| 彝良县| 鲁山县| 叙永县| 长汀县| 远安县| 上虞市| 花垣县| 得荣县| 丹凤县| 中宁县| 赣州市| 青铜峡市| 高青县| 舒城县| 彝良县| 米林县| 金门县| 达州市| 怀仁县| 闽清县| 定结县| 孝义市| 长汀县| 乌兰察布市| 岢岚县|