在 x86 中将结构类型的内容推入堆栈

Pushing contents of struct type onto the stack in x86

假设我已经声明了一个这样的结构:

struct VEC
    x   dd  ?
    y   dd  ?
ends

然后我将一些数据声明为结构:

section '.data' data readable writeable
vec1            VEC     5,4
vec2            VEC     3,2

现在,我想将内存位置vec1 和vec2 的内容压入堆栈。我这样做:

push    sizeof.VEC [vec1]           
push    sizeof.VEC [vec2]

这无法编译。返回的错误是:

error: operand size not specified.

我想知道有没有办法把这个struct类型的内容放到栈上。或者这首先在 x86 中是非法的?

我正在 Windows 10 上使用平面汇编程序版本 1.71.49

进行编译

一般来说,我的问题是关于如何让汇编程序使用正确的操作数大小对推送 [mem] 进行编码

这只是一个关于如何让您的汇编程序使用正确的操作数大小对 push [mem] 进行编码的问题。 16 位和 64 位 pushes 可以在 64 位模式下编码,但 32 位 pushes 不能。 REX.W=0 push something 作为非法指令出错,这与 Intel 的 insn ref 手册声称操作数大小可能被 66H 或 REX.W:

覆盖相反

Operand size. The D flag in the current code-segment descriptor determines the default operand size; it may be overridden by instruction prefixes (66H or REX.W). The operand size (16, 32, or 64 bits) determines the amount by which the stack pointer is decremented (2, 4 or 8).

请注意,这是记录 32 位和 64 位模式。 32 位推送当然可以在 32 位模式下使用。 ( 手册链接的 wiki)


由于有很多结构大小无法通过一条指令推送,因此不太可能有任何语法可以根据结构大小选择字、双字或四字操作数大小。不过,如果您确实需要,您可以自己使用宏来完成。

push 大型结构不是正常调用约定的工作方式,因此这是没有语法糖的另一个原因。通常太大而无法放入寄存器的对象通过引用传递。较小的对象可以按值传递。所以你不能只参数化push的操作数大小来制作灵活的代码;您需要使用宏来发出不同的指令以按值传递与按引用传递,具体取决于结构的大小。

由于您的结构是 64 位的,您只能在 64 位模式下使用一条指令推送整个结构:

push qword [vec1]
push qword [vec2]

(或 qword ptr,如果 FASM 使用 MASM 语法而不是 NASM)。