查看使用VC ++ 2003/2005编译的此C代码。
#include <stdio.h>
#include <windows.h>
void WINAPI SomeFunction(WORD a, WORD b)
{
printf("%d + %d = %d\n", a, b, a + b);
}
int main()
{
__asm {
MOV EAX, 5
MOV EBX, 6
PUSH EBX
PUSH EAX
CALL SomeFunction
}
return 0;
}
在这个ASM代码中,我将两个DWORD
(4字节)参数(据我所知默认情况下)传递给期望两个SomeFunction()
的{{1}}函数(2 bytes)参数,并且完美地工作(输出WORD
)。
1)为什么会这样?
知道该函数需要两个5 + 6 = 11
个参数,我会这样做:
WORD
调试时会抛出分段错误。
2)为什么不有效?
提前致谢!
答案 0 :(得分:3)
第一个可行,因为Win32 ABI表示任何大小小于或等于4个字节的参数都将作为4个字节传递,必要时填充。因此,16位字实际上作为32位传递。这就是你在做什么。
第二个不起作用,因为它做了不同的事情:
MOV WORD PTR [EAX], 5
该行将5
移动到从EAX
指向的内存位置开始的16位字。但是EAX
以前没有加载有效的内存地址。此外,您正在推动指针(WORD*
?)。
为了在堆栈中传递16位值,您可以使用:
MOV AX, 5
MOV BX, 6
PUSH AX
PUSH BX
但这又是Win32 ABI,因为堆栈总是32位对齐。
有趣的是,如果您通过值(未经测试)传递此结构将会有效:
struct WW
{
WORD a, b;
};
void WINAPI SomeFunction(WW w)
{
printf("%d + %d = %d\n", w.a, w.b, w.a + w.b);
}
int main()
{
__asm {
MOV BX, 6 // the parameters are reversed, methinks
MOV AX, 5
PUSH BX
PUSH AX
CALL SomeFunction
}
return 0;
}
那是因为结构的字段以4个字节(sizeof(WW)==4
)打包,所以这是复制到堆栈的内容。
当然,使用16位寄存器并不好玩。这可能更好:
MOV EAX 0x00060005
PUSH EAX
一次性复制整个32位结构。