fastcall 和 asmlinkage

linux操作系統支持多種CPU架構,比如x86、ppc和arm等,參數傳遞的方式是不一樣的。

ARM對函數調用過程中的傳參定義了一套規則,即 ATPCS,規則中明確指出ARM中R0-R4都是作爲通用寄存器使用,超過4個參數的在局部棧中保存,在函數調用時處理器從R0-R4中獲取參數,在函數返回時再 將需要返回的參數一次存到R0-R4中,也就是說可以將函數參數直接存放在寄存器中,而x86體系結果是通過棧來進行參數傳遞的。

所以爲了嚴格區別函數參數的存放位置,引入了兩個標記,即 asmlinkage和FASTCALL,前者表示將函數參數存放在局部棧中,後者則是通知編譯器參數用寄存器保存起來。

1、X86體系架構

#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))
#define FASTCALL(x) x __attribute__((regparm(3)))
#define fastcall __attribute__((regparm(3)))

__attribute__是關鍵字,是gcc的C語言擴展,regparm(0)表示不從寄存器傳遞參數
如果是__attribute__((regparm(3))),那麼調用函數的時候參數不是通過棧傳遞,而是直接放到寄存器裏,被調用函數直接從寄存器取參數。
__attribute__((regparm(3))):告訴gcc編譯器這個函數可以通過寄存器傳遞多達3個的參數,這3個寄存器依次爲EAX、EDX 和 ECX。更多的參數才通過堆棧傳遞。這樣可以減少一些入棧出棧操作,因此調用比較快。

2、ARM

#ifndef FASTCALL
#define FASTCALL(x) x
#define fastcall
#endif

#ifndef asmlinkage
#define asmlinkage CPP_ASMLINKAGE
#endif

#ifdef __cplusplus
#define CPP_ASMLINKAGE extern "C"
#else
#define CPP_ASMLINKAGE
#endif

在ARM中,通過定義fastcall,將前兩個(或若干個)參數由寄存器傳遞,其餘參數還是通過堆棧傳遞(從右到左)。 定義asmlinkage爲空或者extern "C"。


之所以要進行區分,是因爲通過內陷進入系統調用的時候,內核被告知從何處獲取參數。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章