gcc 在 i386 / x86_64 的 machine dependent 參數 (-m) 中,有 1 個參數與參數的傳遞相關的:-mregparm=num,這個參數的用途與先前提到的 "__attribute((regparm(?))__" 作用相同*2。
-mregparm 用來指定有多少個 integer 的參數可以透過暫存器(register)來傳遞, 以下是 -mregparm 的 man(GCC(1)):
Intel 386 and AMD x86-64 Options ... -mregparam Use a different function-calling convention where the first two arguments are passed in registers.
kernel 的編譯設定中(menuconfig),也提供一個選項來設定「暫存器參數的傳遞」。這個設定位於 menuconfig 的 「Processor type and features|Use register arguments (EXPERIMENTAL) (NEW)」,Jollen 所使用的 kernel 版本是 Linux v2.6.11 (for i386),如果您的 kernel 不是 i386 或是版本不同,您可能無法在這個地方找到此設定項。
Kconfig 與 -mregparam
以下是節錄自 arch/i386/Kconfig 的內容:
config REGPARM bool "Use register arguments (EXPERIMENTAL)" depends on EXPERIMENTAL default n help Compile the kernel with -mregparm=3. This uses a different ABI and passes the first three arguments of a function call in registers. This will probably break binary only modules.
This feature is only enabled for gcc-3.0 and later - earlier compilers generate incorrect output with certain kernel constructs when -mregparm=3 is used.
當我們把 REGPARM 設定為 'y' 後,Makefile 裡的 CONFIG_REGPARM 值也會是 'y'。當 CONFIG_REGPARM=y 時,cflags-y 便加 "-mregparm=3" 的參數,請注意 Kernel 2.6.x 必須以 3.2.x 以上的 gcc 來編譯*1。相關的 Makefile 節錄如下(arch/i386/Makefile):
# -mregparm=3 works ok on gcc-3.0 and later # GCC_VERSION := $(call cc-version) cflags-$(CONFIG_REGPARM) += $(shell if [ $(GCC_VERSION) -ge 0300 ] ; then echo "-mregparm=3"; fi ;)
# Disable unit-at-a-time mode, it makes gcc use a lot more stack # due to the lack of sharing of stacklots. CFLAGS += $(call cc-option,-fno-unit-at-a-time)
CFLAGS += $(cflags-y)
最後,CFLAGS 的值會加上 '$(cflgs-y)',我們知道 CFLAGS 是 gcc 的編譯參數設定變數,所以當 gcc 在編譯 kernel 時,便會套用 "-mregparm=3" 的參數。
Also See |
Jollen's Blog 使用 Github issues 與讀者交流討論。請點擊上方的文章專屬 issue,或 open a new issue
您可透過電子郵件 jollen@jollen.org,或是 Linkedin 與我連絡。更歡迎使用微信,請搜尋 WeChat ID:jollentw