如何在 x86 程序集中按值传递结构
How to pass a struct by value in x86 assembly
我正在尝试从 masm 中的 windows api 调用一个函数。
这是签名:
BOOL WINAPI SetConsoleScreenBufferSize(
_In_ HANDLE hConsoleOutput,
_In_ COORD dwSize
);
COORD 结构 dwSize 是按值传递的,但是当我尝试调用它时,该函数失败了。
看起来像这样:
.DATA
dwSize COORD <20, 20>
.CODE
INVOKE SetConsoleScreenBufferSize,
hConsoleOutput,
dwSize
这会导致类型错误,程序不会 assemble。如果我传递对结构的引用,程序 assembles 但函数不起作用。我试过其他按值接受结构的函数,但没有成功。
COORD 只是两个 16 位数字打包在一起并作为正常的 32 位数字传递。
MSVC (x86) 转
COORD cord = { 0x666, 0x42 };
SetConsoleScreenBufferSize(0, cord);
进入
33db xor ebx,ebx
66c745986606 mov word ptr [ebp-68h],666h ; store cord.x
66c7459a4200 mov word ptr [ebp-66h],42h ; store cord.y
ff7598 push dword ptr [ebp-68h] ; push the whole struct
53 push ebx ; push 0
ff1540104000 call dword ptr [image00400000+0x1040 (00401040)] ; SetConsoleScreenBufferSize
在 push
之后但在 call
之前,堆栈开始于:
00000000 00420666 ...
xor-zeroing 一个寄存器,然后将其压入,这是一个错过的优化与 push 0
的立即数零。首先存储到堆栈也只是因为源代码是在禁用优化的情况下编译的。
Hans 是正确的 Invoke
不明白如何按值传递结构。 COORD
是 2 个 16 位值,恰好是 DWORD 的大小。在 COORD
的情况下,您可以将其转换为 DWORD 作为 Invoke
的参数。这应该有效:
.DATA
dwSize COORD <20, 20>
.CODE
INVOKE SetConsoleScreenBufferSize,
hConsoleOutput,
DWORD PTR [dwSize]
注意:重要的是要理解,因为 COORD
恰好是 DWORD 的大小,所以我们可以避免这种情况。对于没有可以直接压入堆栈的大小的结构,您必须在堆栈上构建结构并使用 CALL
指令而不是 Invoke
.
我正在尝试从 masm 中的 windows api 调用一个函数。
这是签名:
BOOL WINAPI SetConsoleScreenBufferSize(
_In_ HANDLE hConsoleOutput,
_In_ COORD dwSize
);
COORD 结构 dwSize 是按值传递的,但是当我尝试调用它时,该函数失败了。
看起来像这样:
.DATA
dwSize COORD <20, 20>
.CODE
INVOKE SetConsoleScreenBufferSize,
hConsoleOutput,
dwSize
这会导致类型错误,程序不会 assemble。如果我传递对结构的引用,程序 assembles 但函数不起作用。我试过其他按值接受结构的函数,但没有成功。
COORD 只是两个 16 位数字打包在一起并作为正常的 32 位数字传递。
MSVC (x86) 转
COORD cord = { 0x666, 0x42 };
SetConsoleScreenBufferSize(0, cord);
进入
33db xor ebx,ebx
66c745986606 mov word ptr [ebp-68h],666h ; store cord.x
66c7459a4200 mov word ptr [ebp-66h],42h ; store cord.y
ff7598 push dword ptr [ebp-68h] ; push the whole struct
53 push ebx ; push 0
ff1540104000 call dword ptr [image00400000+0x1040 (00401040)] ; SetConsoleScreenBufferSize
在 push
之后但在 call
之前,堆栈开始于:
00000000 00420666 ...
xor-zeroing 一个寄存器,然后将其压入,这是一个错过的优化与 push 0
的立即数零。首先存储到堆栈也只是因为源代码是在禁用优化的情况下编译的。
Hans 是正确的 Invoke
不明白如何按值传递结构。 COORD
是 2 个 16 位值,恰好是 DWORD 的大小。在 COORD
的情况下,您可以将其转换为 DWORD 作为 Invoke
的参数。这应该有效:
.DATA
dwSize COORD <20, 20>
.CODE
INVOKE SetConsoleScreenBufferSize,
hConsoleOutput,
DWORD PTR [dwSize]
注意:重要的是要理解,因为 COORD
恰好是 DWORD 的大小,所以我们可以避免这种情况。对于没有可以直接压入堆栈的大小的结构,您必须在堆栈上构建结构并使用 CALL
指令而不是 Invoke
.