發表日期: 2007-04-27 17:49
分析系統呼叫的實現時看到這麼一段**,令人不禁拍案叫絕。
系統呼叫的引數傳遞,前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平台下的延遲槽有深刻的理解,故而才能有如此神乎其技的妙用。
MIPS 組合語言程式設計的藝術(龍芯適用)
分析系統呼叫的實現時看到這麼一段 令人不禁拍案叫絕。系統呼叫的引數傳遞,前4個引數通過a0 a3傳,後面的引數要通過棧來傳,目前核心 系統呼叫最長的引數個數為8。用棧傳遞引數時,涉及到要將位於使用者空間的引數先複製到核心空間 核心棧 因為系統呼叫的引數個數不定,因此就需要判斷引數個數為5 6 7 8...
組合語言程式設計
1.彙編語句的三種基本型別 2.標號相關 3.變數相關 4.運算元定址方式 buffer dw 500 x 17 rept 500 這是乙個重複巨集,以下重複彙編500遍 x x 979 mod 65535 這句話我也不懂 dw x endm 巨集在這裡結束transto10 proc near 函...
組合語言程式設計
乙個完整的源程式通常由若干邏輯段組成,包括資料段 附加段 堆疊段和 段。它們分別對映到儲存器中的物理段上。每個邏輯段以segment語句開始,以ends結束,整個源程式用end語句結尾。段中存放源程式的所有指令碼 資料 變數等則放在資料段和附加段中。程式中可以定義堆疊段,也可以直接利用系統中的堆疊段...