MIPS 組合語言程式設計的藝術(龍芯適用)

2021-04-12 23:48:42 字數 1609 閱讀 4817

分析系統呼叫的實現時看到這麼一段**,令人不禁拍案叫絕。

系統呼叫的引數傳遞,前4個引數通過a0~a3傳,後面的引數要通過棧來傳,目前核心

系統呼叫最長的引數個數為8。

用棧傳遞引數時,涉及到要將位於使用者空間的引數先複製到核心空間(核心棧)。

因為系統呼叫的引數個數不定,因此就需要判斷引數個數為5、6、7、8 不同情況時,

相應的複製操作個數。5個引數時需要複製個數為1,6個時為2,以此類推。

通常的解決方法是用switch語句,這個編譯出來,得要四條分支判斷語句吧

看看核心的一些牛人怎麼實現:

la  t1, 5f          # 標號5所示之位址入t1

subu    t1, t3        # t3 的內容為當前系統呼叫引數個數減去5,再乘以4

# 這個已經預先計算好,儲存於系統呼叫表每項的第二個

#  字段,用時直接載入。

# 另外,此前已經判斷過,t3 的內容大於等於0

1:  lw  t5, 16(t0)      # t0 的內容為使用者空間第乙個引數的位址

.set    push

.set    noreorder

.set    nomacro

jr  t1

addiu  t1, 6f - 5f   # 妙用分支延遲槽

2:  lw  t8, 28(t0)      # 取使用者空間第8個引數

3:  lw  t7, 24(t0)      # 取使用者空間第7個引數

4:  lw  t6, 20(t0)      # 取使用者空間第6個引數

5:  jr  t1

sw t5, 16(sp)      # 第5個引數進入核心棧

c:  sw  t8, 28(sp)      # 第8個引數進入核心棧

b:  sw  t7, 24(sp)      # 第7個引數進入核心棧

a:  sw  t6, 20(sp)      # 第6個引數進入核心棧

6:  j   stack_done      # 引數複製完畢,返回

nop只用兩條 jr 指令,效率大大提高!簡直妙不可言!

下面詳細分析之:

(1) t3 的值,在引數個數為5 時,t3 為0,6 時為4,7 時為8,8 時為12

這個 t3 在這裡,實際上是用來表示相對於標號5處的位址偏移! 因為mips/godson下,

指令的長度都是4個位元組。因此 t3 值為4(引數個數為6)時,第乙個 jr t1 是跳轉到

標號4處開始執行的。

(2) 第乙個 jr t1 用來解決從使用者空間複製資料操作的個數問題,相對應的,則是解決寫入

操作的個數問題,這個用第二個 jr t1 來解決。在此之前,更新 t1 的指令(addiu)的

位置放的很巧妙,置於第乙個 jr t1 的延遲槽中,不占用標號4與標號5之間的空間。

(3) 可以看到引數個數為5時,第二個 jr t1 直接跳轉到標號6處執行,將第5個引數寫入內

核棧的操作置於延遲槽中;引數個數為6時,會跳轉到標號a處執行;引數個數為8時,會

跳轉到標號c處執行,依次完成第5、8、7、6引數的寫入。

結論:該段程式的作者對mips平台下的延遲槽有深刻的理解,故而才能有如此神乎其技的妙用。

龍芯組合語言程式設計藝術

發表日期 2007 04 27 17 49 分析系統呼叫的實現時看到這麼一段 令人不禁拍案叫絕。系統呼叫的引數傳遞,前4個引數通過a0 a3傳,後面的引數要通過棧來傳,目前核心 系統呼叫最長的引數個數為8。用棧傳遞引數時,涉及到要將位於使用者空間的引數先複製到核心空間 核心棧 因為系統呼叫的引數個數...

mips組合語言筆記

因為乙個課程涉及mips組合語言,自己做一些筆記。部落格還有乙個b站的,查mips能查到那個文章。注意 彙編使用的位址也是邏輯位址,有偏移量,通過硬體進行轉化。比如乙個 la操作就會進行對記憶體的好幾次訪問 具體暫存器操作貼乙個圖 1 往a0裡寫資料。3種方式。1 寫立即數 li a0 1 2 暫存...

C語言轉成MIPS組合語言

功能 隨機輸入兩個整數,然後計算這兩個數的最小公倍數和最大公約數,並作為計算結果輸出。include stdio.h include conio.h int main a num1 b num2 while b 0 一直重複賦值和計算,直到找到正確結果 printf gongyueshu d n a...