如何在汇编中调用f1函数的第三个参数中的传递函数(* f2)? 声明如下:
scenario02 ramp to 70 over y seconds
我想将v1传递给v3,v2传递给v4,调用函数f2,并返回值
extern float f1(int v1, float v2, float (*f2)(int v3, float v4));
我应该用什么来代替问号?
答案 0 :(得分:5)
没有" Abi64"。由于您标记了MASM问题,我们可以猜测您正在使用Windows平台,而且显然是#34; 64"这意味着这是64位代码,因此可以极大地缩小可能性。但是,Windows上仍有两种常见的64位代码调用约定。其中一个是__vectorcall
,另一个是Microsoft x64调用约定(最初发明用于使所有其他调用约定过时但是......没有)的那个约定。
由于Microsoft x64调用约定是最常见的,并且在这种特殊情况下,使用__vectorcall
不会改变任何内容,我将假设它是您的#&# 39;重新使用。然后所需的代码变得非常微不足道。您需要做的就是从f1
跳转到f2
,因为堆栈的设置方式相同。 f1
的前两个参数是应传递给f2
的两个参数,f2
的返回值是f1
的返回值。因此:
f1:
rex_jmp r8 ; third parameter (pointer to f2) is passed in r8
这不仅可以轻松编写,而且是大小和速度的最佳实现
如果需要,您甚至可以事先修改v1
或v2
参数,例如:
f1:
inc ecx ; increment v1 (passed in ecx)
; multiply v2 (xmm1) by v1 (ecx)
movd xmm0, ecx
cvtdq2ps xmm0, xmm0
mulss xmm1, xmm0
rex_jmp r8 ; third parameter (pointer to f2) is passed in r8
如果您想要做一些更复杂的事情,请按照以下方式进行操作:
f1:
sub rsp, 40 ; allocate the required space on the stack
call r8 ; call f2 through the pointer, passed in r8
add rsp, 40 ; clean up the stack
ret
请注意,您不需要在问题中显示的序言/结语代码,但如果您选择包含该代码,则不会有任何损害。
但是,您在问题中显示的示例代码中执行的参数重排是错误!在Microsoft x64调用约定中,第一个最多四个整数参数在RCX,RDX,R8和R9中从左到右传递到寄存器中。所有其他整数参数都在堆栈上传递。第一个最多四个浮点值也在寄存器中传递,从左到右,在XMM0,XMM1,XMM2和XMM3中。其余的都是在堆栈上传递的,结构对于寄存器来说太大了。
但是,奇怪的是,插槽是固定的#34;因此,即使你有一个整数和fp args混合,也只能使用4个寄存器参数。因此:╔═══════════╦══════════════════════════╗
║ ║ TYPE ║
║ PARAMETER ╠═════════╦════════════════╣
║ ║ Integer ║ Floating-Point ║
╠═══════════╬═════════╬════════════════╣
║ First ║ RCX ║ XMM0 ║
╠═══════════╬═════════╬════════════════╣
║ Second ║ RDX ║ XMM1 ║
╠═══════════╬═════════╬════════════════╣
║ Third ║ R8 ║ XMM2 ║
╠═══════════╬═════════╬════════════════╣
║ Fourth ║ R9 ║ XMM3 ║
╠═══════════╬═════════╩════════════════╣
║ (rest) ║ on stack ║
╚═══════════╩══════════════════════════╝
第二个参数是传递的第一个浮点值并不重要。它没有进入XMM0,因为它是第一个浮点值,它在XMM1中,因为它是第二个参数,因此在第二个"槽"中。 (这与the x86-64 System V ABI不同,其中前6个整数args进入寄存器,无论是否存在FP args)。
有关Windows参数传递的更详细文档可用here,包括示例。
答案 1 :(得分:-2)
装配代码因使用的微控制器而异。
不完全是您正在寻找的,但是遵循在具有intel核心I7的Windows平台上生成的汇编代码: -
C代码: -
extern float f1(int v1, float v2, float (*f2)(int v3, float v4))
{
float a = 10.0;
int b = 12;
f2(b, a);
return a+ 12.5;
}
汇编代码: -
_f1:
pushl %ebp
movl %esp, %ebp
subl $40, %esp
movl LC0, %eax
movl %eax, -12(%ebp)
movl $12, -16(%ebp)
movl -12(%ebp), %eax
movl %eax, 4(%esp)
movl -16(%ebp), %eax
movl %eax, (%esp)
movl 16(%ebp), %eax
call *%eax
fstp %st(0)
flds -12(%ebp)
flds LC1
faddp %st, %st(1)
leave
ret
希望这会有所帮助。