PowerPC彙編指令集簡析 1

2021-05-28 10:57:01 字數 3473 閱讀 3090

在了解powerpc彙編指令前,需要先看下程式設計所用的暫存器模型,powerpc系統結構為大多數運算指令都定義了register-register的操作,這些操作的源運算元從暫存器取得,或作為嵌入指令操作碼中的立即數提供。這裡的e300核可分為使用者程式設計模型和管理員程式設計模型,該模型有32個gpr、32個fpr、特殊目的暫存器spr和一些功能暫存器,下圖為二者的示意圖:

上面這些暫存器可能不太好理解,因為名字和intel彙編不一樣,其實,可以這樣理解,gpr就相當於eax/ebx/ecx,而ctr則完全就是ecx的功能,是吧?區別就是沒有堆疊而已咯。cr被分為8段,每段4位,分別代表lt、gt、eq和so(小於、大於、等於和溢位);lr用於記錄跳轉位址;特殊暫存器xer用於記錄溢位和進製標誌;fpscr用於記錄浮點運算型別和異常等。

再看下指令集,大部分的cpu指令集可分為:資料讀寫、數值計算、流程控制和裝置管理四個部分,由於powerpc使用risc,指令字長為32bit,endian一般是可調的,預設為大端,另外,powerpc沒有棧,所以程式需要自己實現相關操作。首先為運算和邏輯指令,列舉如下:

它們與通用暫存器有關,源資料來自gpr 或16 位立即數,目的是gpr 暫存器,操作為32 位,gpr 中存放32 位更新資料。大多數指令都可以根據字面意思理解其作用,注意還有乙個「cntlzw」指令,意為計算字中的第乙個0,用於在乙個字中找到1時將乙個指令中的0的數量找出,它在決定例外暫存器中最高優先服務時有用。

下面是資料讀寫指令,它們對資料在儲存器中核通用暫存器中的傳送很有用,若資料小於傳送長度(單字,半字或位元組),指令會使資料變位為32位,將不同位填0或符號擴充套件。指令列舉如下:

這裡需要注意的是上面列舉的lbz和lhz兩個指令並不完全等同於mov al,[ebx]和mov ax,[ebx+10]這兩個,因為前面兩個是將位元組和半字載入到r3時還清空了高位,而後兩條指令只是載入資料到eax,並不會清空高位。

另外,還有兩個指令sthbrw和stwbrx,對powerpc訪問小端格式資料很有用,它們允許訪問這樣的資料,若資料以小端順序進入匯流排,就把它存為大端順序。

好了,現在來詳細看下賦值指令,下面是最常見的賦值**:

lis    r3,0x1234

addi r3,r3,0x5678

這段**的含義是將0x12345678載入到暫存器r3中。因為在risc下,powerpc的每條指令都是32bit,除去指令和暫存器引數編碼,只剩下16bit的長度描述立即數,如立即數載入指令li:

這樣立即數simm只有16位,所以需要兩次載入,使用lis(立即數載入並左移)和addi(立即數加法)兩條指令完成。

再看下powerpc不同的子程式呼叫:

func:       /* 子程式入口 */

blr /* 返回(跳轉到lr位址) */

start:

bl func /* 呼叫func(跳轉並儲存位址到lr) */

li r1,1 /* 設定r1、r3 */

li r3,1

sc /* 系統呼叫,結束程式 */

這裡的呼叫由powerpc使用lr暫存器完成,在bl指令跳轉前,下一條指令li r1,1的位址會被儲存在lr,而執行的func中的blr時,系統會跳到lr表示的位址,完成返回。

再來介紹下特殊暫存器的操作指令,它們可以完成特殊用途暫存器之間和通用暫存器之間的資料交換,不可以直接對特殊用途暫存器中的值進行處理,但是,可以將乙個值先拷貝到乙個通用暫存器上處理,再將資訊存到特殊用途暫存器上。下面是指令集合:

這裡回顧下,powerpc裡沒有堆疊,那用什麼實現模擬呢?看下面的例子:

f1:

mflr r2 /*儲存lr中記錄的位址到r2*/

stw r2,-8(r1) /*記錄r2的值到mem[r1-8]*/

addi r1,r1,-60 /*r1後移60個位元組,完成進棧操作*/

...addi r1,r1,60 /*r1前移60個位元組,準備出棧*/

lwz r2,-8(r1) /*讀出老的lr值到r2*/

mtfr r2 /*將r2的內容複製到lr*/

blr /*返回(跳轉到lr位址)*/

start:

...bl f1 /*呼叫f1(跳轉並保持位址到lr)*/

看到了吧,雖然沒有提供棧的相關指令(push/pop/call/ret),但應用程式可以用r1模擬棧指標,實現多層呼叫對lr的記錄和恢復。

前面說了,powerpc指令為32位長,指令內僅有16位用於載入常量值,由於位址最多可達到64位,所以我們可以採用每次一段的方式載入位址,匯程式設計序中的@符號指示匯程式設計序給出乙個符號值的特殊處理形式:@highest:表示乙個常量的第48-63位;@higher:表示乙個常量的第32-48位;@h:16-31位;@l:0-15位。

下面是我們的乙個稍大點的powerpc匯程式設計序總結下上面的指令集,實現的功能就是載入兩個值並相加,最後退出,以結果為狀態**輸出。**如下:

#sum.s,第乙個powerpc匯程式設計序

.data

.align 3

#此處裝載兩個值

first_value:

.quad 1

second_value:

.quad 2

#寫」.opd」(official procedure descriptor)

.section 「.opd」,」aw」

.align 3

#._start的程式描述符,即為程式名

.global _start

_start:

.quad .start, .toc.@tocbase,0

#._text為程式**段

.text

._start:

#裝載位址高位

lis r7,first_value@highest

ori r7,r7,first_value@higher

#shift these up to the high-order bits

rldier r7,r7,32,31

#裝載位址低位

oris r7,r7,first_value@h

ori r7,r7,first_value@l

#將第乙個值載入暫存器4

ld r4,0(r7)

lis r7,second_value@highest

ori r7,r7,second_value@higher

rldicr r7,r7,32,31

oris r7,r7,second_value@h

ori r7,r7,second_value@l

ld r5,0(r7)

#二者相加並存到暫存器6

add r6,r4,r5

#程式退出

li 0,1 #暫存器0為系統呼叫

mr r3,r6 #將結果移到暫存器3中

sc #對核心進行系統呼叫

彙編指令集

1.通用資料傳送指令.mov 傳送字或位元組.movsx 先符號擴充套件,再傳送.movzx 先零擴充套件,再傳送.push 把字壓入堆疊.pop 把字彈出堆疊.pusha 把ax,cx,dx,bx,sp,bp,si,di依次壓入堆疊.popa 把di,si,bp,sp,bx,dx,cx,ax依次彈...

彙編指令集

一 資料傳輸指令 它們在存貯器和暫存器 暫存器和輸入輸出埠之間傳送資料.1.通用資料傳送指令.mov 傳送字或位元組.movsx 先符號擴充套件,再傳送.movzx 先零擴充套件,再傳送.push 把字壓入堆疊.pop 把字彈出堆疊.pusha 把ax,cx,dx,bx,sp,bp,si,di依次壓...

彙編指令集

ja jnbe 不小於或不等於時轉移.jae jnb 大於或等於轉移.jb jnae 小於轉移.jbe jna 小於或等於轉移.以上四條,測試無符號整數運算的結果 標誌c和z jg jnle 大於轉移.jge jnl 大於或等於轉移.jl jnge 小於轉移.jle jng 小於或等於轉移.以上四條...