6.3 Win64 Output Format
6.3.1 Win64 Basics
This output format, that is selected with the -win64 commandline option, is a variant of the
COFF output format. It's commonly used to create object modules for 64-bit Windows.
The default calling convention is the Win64 FASTCALL implementation.
6.3.2 Directive INVOKE in Win64
Unlike the 64-bit version of Masm, which doesn't support INVOKE anymore, JWasm still
does; however, please be aware of some peculiarities:
- in theory, using INVOKE requires the FRAME attribute for PROC. It will
work without FRAME, but Win64 SEH won't be happy with it then.
- the default implementation in 64-bit is very simple: for each INVOKE register
RSP is reduced by the space required for the arguments, then the call
is issued and finally register RSP is restored. To enable a more efficient code
generation see OPTION WIN64, INVOKE Stack Space Reservation - this
option is not active as default because it virtually requires a certain programming style.
- there is no additional check that the stack is aligned to 16 byte. The
PROC's FRAME attribute ensures that the stack is correctly aligned after
the prologue is done. However, it's the programmers responsibility that
the stack is still aligned when the code generated by INVOKE starts.
- parameter names listed behind the PROC directive will always refer to
the parameter's shadow space on the stack. However, on a procedure's entry
the actual values of the first four parameters are hold in registers, and
the value of the associated shadow spaces are undefined. See OPTION WIN64,
Store Register Arguments, how to make JWasm automatically save the register arguments and thus
initialize the shadow space on a procedure's entry.
6.3.3 Win64 Structured Exception Handling (SEH)
SEH in Win64 differs significantly from the implementation in Win32.
It's very well possible to ignore Win64 SEH for assembly. However,
if an assembly routine wants to comply to these rules, a thorough
understanding of the Win64 ABI is necessary. Masm ( the 64-bit
version ) supplies some "primitives" for SEH support (.ALLOCSTACK,
.PUSHREG, .SAVEREG, ...), along with a new FRAME attribute for the
PROC directive. These features are also supported by JWasm. See sample
Win64_3 how the "primitives" are to be used for SEH support.
The big disadvantage is that using the FRAME keyword in Masm "disables"
most of the other high level features combined with PROC (function
parameters, locals and registers saved with USES) because no function
prologues and epilogues are generated anymore. Additionally, the
implementation at least in Masm v8 seems to be a bit buggy, at least in Masm v8.
Because of this and to ease the usage of SEH in Win64 there is a new
directive implemented in JWasm:
OPTION FRAME:AUTO
If this option is set, JWasm will create Win64 SEH-compatible prologues
and epilogues. If the option is off, JWasm will behave Masm-compatible,
that is, FRAME found in a PROC directive will disable automatic
prologue/epilogue generation. See sample Win64_3e how this option
is supposed to be used.
As for the PROC syntax: The Masm documentation states that FRAME can be
used in combination with USES and procedure parameters and must be
located behind all parameters. However, this syntax isn't accepted by
any Masm version. The only syntax which Masm will accept without being
confused is FRAME as the one and only parameter for PROC. Therefore
JWasm doesn't follow the Masm documentation in this point: the optional
FRAME keyword is expected *before* the procedure parameters. The syntax
in JWasm is:
procname PROC [public] FRAME[:exc_handler] [USES <reglist>] [parameters]
The SEH "primitives" will generate some additional data in segments
.pdata and .xdata. This data is somewhat hidden, but JWasm will display
the corresponding data definitions in the listing if option -Sg is set.
Finally, JWasm's default behavior of INVOKE isn't fully SEH-compatible, because the
stack pointer is temporarily changed to make room for arguments. To make
INVOKE comply to SEH, OPTION WIN64
INVOKE Stack Space Reservation has to be used.