Lets say I have declared a struct like so:
struct VEC
x dd ?
y dd ?
ends
Then I declare some data as struct:
section '.data' data readable writeable
vec1 VEC 5,4
vec2 VEC 3,2
Now, I wish to push the contents of memory locations vec1 and vec2 to the stack. I do something like this:
push sizeof.VEC [vec1]
push sizeof.VEC [vec2]
This doesn't compile. The error returned is:
error: operand size not specified.
I want to know if there is any way to put the contents of this struct type onto the stack. Or is this illegal in x86 in the first place?
I am compiling this on Windows 10 using flat assembler version 1.71.49
In general, my question is about how to get the assembler to encode a push [mem] with the right operand-size
This is just a question of how to get your assembler to encode a push [mem]
with the right operand-size. 16bit and 64bit push
es are encodable in 64bit mode, but not 32bit push
es. REX.W=0 push something
faults as an illegal instruction, contrary to Intel's insn ref manual claiming that the operand-size may be overridden with 66H or 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).
Note that this is documenting 32 and 64bit mode. 32bit pushes are of course available in 32bit mode. (x86 wiki for links to the manual)
Since there are lots of struct sizes that aren't pushable with a single instruction, it's unlikely that there's any syntax for choosing a word, dword or qword operand-size based on the struct size. You might use macros to do it yourself, though, if you really wanted.
push
ing large structs is not how normal calling conventions work, so that's another reason there isn't syntactic sugar for it. Normally objects too large to fit in a register are passed by reference. Smaller objects can be passed by value. So you can't just parameterize the operand-size of the push
to make flexible code; you'd need to use a macro to emit a different instruction to pass by value vs. pass by reference, depending on the size of the struct.
Since your struct is 64bit, you can only push a whole struct with a single instruction in 64bit mode:
push qword [vec1]
push qword [vec2]
(Or qword ptr
, if FASM uses MASM syntax instead of NASM).