我有一个Linux x64的汇编应用程序,我通过寄存器将参数传递给函数,因此我使用某种特定的调用约定,在本例中为fastcall。现在我想从程序集应用程序调用一个C函数,比如说,需要10个参数。我是否必须切换到cdecl
并通过堆栈传递参数,而不管我的应用程序中的其他地方我通过寄存器传递它们?是否允许在一个应用程序中混合调用约定?
答案 0 :(得分:2)
当然可以。呼叫约定基于每个功能应用。这是一个非常有效的应用程序:
{
"name": "elm-webpack-starter",
"description": "Webpack setup for writing Elm apps",
"version": "0.8.4",
"license": "MIT",
"author": "Peter Morawiec",
"repository": {
"type": "git",
"url": "https://github.com/moarwick/elm-webpack-starter"
},
"scripts": {
"start": "webpack-dev-server --hot --inline --port 8001",
"build": "rimraf dist && webpack && mv dist/*.eot dist/static/css/ && mv dist/*.woff* dist/static/css/ && mv dist/*.svg dist/static/css/ && mv dist/*.ttf dist/static/css/",
"reinstall": "npm i rimraf && rimraf node_modules && npm uninstall -g elm && npm i -g elm && npm i && elm package install"
},
"devDependencies": {
"autoprefixer": "^6.3.6",
"bootstrap-sass": "^3.3.6",
"copy-webpack-plugin": "^4.0.1",
"css-loader": "^0.26.1",
"elm": "^0.18.0",
"elm-hot-loader": "^0.5.4",
"elm-webpack-loader": "^4.1.1",
"extract-text-webpack-plugin": "^1.0.1",
"file-loader": "^0.9.0",
"html-webpack-plugin": "^2.17.0",
"jquery": "^3.1.0",
"node-sass": "^4.2.0",
"postcss-loader": "^1.1.1",
"rimraf": "^2.5.2",
"sass-loader": "^4.0.0",
"style-loader": "^0.13.1",
"url-loader": "^0.5.7",
"webpack": "^1.13.1",
"webpack-dev-server": "^1.14.1",
"webpack-merge": "^2.4.0"
}
}
答案 1 :(得分:2)
我假设通过 fastcall ,你的意思是SysV ABI使用的amd64调用约定(即Linux使用的),其中前几个参数在rdi
中传递,{{1 }和rsi
。
ABI略显复杂,以下是简化。您可能需要阅读the specification了解详细信息。
一般来说,前几个(最左边的)整数或指针参数放在寄存器rdx
,rdi
,rsi
,rdx
,rcx
中和r8
。浮点参数在r9
中传递给xmm0
。如果寄存器空间耗尽,则从右到左通过堆栈传递其他参数。例如,要调用具有10个整数参数的函数:
xmm7
你需要这样的代码:
foo(a, b, c, d, e, f, g, h, i, k);
对于您的具体示例,mov $a,%edi
mov $b,%esi
mov $c,%edx
mov $d,%ecx
mov $e,%r8d
mov $f,%r9d
push $k
push $i
push $h
push $g
call foo
add $32,%rsp
:
getnameinfo
您将int getnameinfo(
const struct sockaddr *sa,
socklen_t salen,
char *host,
size_t hostlen,
char *serv,
size_t servlen,
int flags);
中的sa
,rdi
中的salen
,rsi
中的host
,rdx
传递hostlen
1}},rcx
中的serv
,r8
中的servlen
和堆栈中的r9
。
答案 2 :(得分:-1)
你可以,但你不需要。
__attribute__((fastcall))
只要求在寄存器中传递前两个参数 - 无论如何,其他所有参数都会自动传递到堆栈上,就像cdecl
一样。这样做是为了不通过选择某个调用约定来限制可以赋予函数的参数数量。
在您的示例中,对于使用fastcall
调用约定调用的函数的10个参数,前两个参数将在寄存器中传递,其余8个自动在堆栈上,就像使用标准调用约定一样。
由于您已选择将fastcall
用于所有其他功能,因此我没有找到您为某个特定功能更改此功能的原因。