When Masm is mentioned, then usually Masm v8.00 is meant, unless stated otherwise. Masm v8.00 also was the first Masm version supporting 64-bit (ML64.EXE).
The Masm documentation itself can be found on numerous places in the web, in plain text, HTML, PDF and Windows Help format. However, it's usually just the documentation that came whith Masm v6.1 - hence a bit outdated nowadays ( the changes from Masm v6 to Masm v8 are listed in Appendix D ).
Options are usually entered via the command line. Additionally, when starting, JWasm will search for environment variable JWASM and handle it similar to the way Masm handles variable ML. Hence it is also possible to enter options via this method.
The options specific to JWasm - and also the options which are handled somewhat differently by JWasm compared to Masm - will be handled in the following chapters.
One major difference should be mentioned here: JWasm does never launch a linker on its own ( which Masm does unless option -c is given ). This makes a few Masm options useless for JWasm, and hence they are not implemented; see Chapter Known Bugs and missing Features for details.
|
For more information, see Binary Output Format.
Chapter Output Formats lists all available output formats.
For more information about COFF, see COFF Output Format.
Chapter Output Formats lists all available output formats.
Chapter Output Formats lists all available output formats.
Use OPTION ELF to set values in the ELF header.
Chapter Output Formats lists all available output formats.
Use OPTION ELF to set values in the ELF header.
Chapter Output Formats lists all available output formats.
If JWlink is used, the <file_name> argument may be omitted. Then JWasm will write the import definitions directly into the object module's linker directive section (section ".drectve"). This works for output formats COFF and ELF only. See sample Win32_7 how to use JWasm and JWlink to create a Windows binary without import libs.
| -Gc | Pascal |
| -Gd | C(decl) |
| -Gr | Fastcall |
| -Gz | Stdcall |
As in all binary formats, the listing will contain a binary map; see Binary Output Format for more details.
Chapter Output Formats lists all available output formats.
For more details about the PE format see PE Output Format.
Chapter Output Formats lists all available output formats.
Option -win64 will also set cpu to x86-64, model to FLAT and default calling convention to FASTCALL. This is to make JWasm compatible with Masm64 (ML64.EXE).
With OPTION WIN64, parameters specific to Win64 may be set.
For more information about Win64, see Win64 Output Format.
Chapter Output Formats lists all available output formats.
| MS CodeView | OMF | 16-bit, Windows and DOS |
| CDB, NTSD | COFF | 32- and 64-bit, Windows |
| WinDbg | COFF | 32- and 64-bit, Windows |
| MS Visual Studio 2008 | COFF | 32-bit[1], Windows |
| MS Visual Studio 2010 | COFF | 32-bit[1], Windows |
| OW WD/WDW | OMF/COFF | 16- and 32-bit, Windows and DOS |
| PellesC IDE | COFF | 32-bit[1], Windows |
| Borland TD/TDW/TD32 | OMF | 16- and 32-bit, Windows and DOS |
| MS CodeView | 16-bit, Windows and DOS |
| MS CDB or NTSD | 32- and 64-bit, Windows |
| MS WinDbg | 32- and 64-bit, Windows |
| MS Visual Studio 2008 | 32-bit[1], Windows |
| MS Visual Studio 2010 | 32-bit[1], Windows |
| Open Watcom WD/WDW | 16- and 32-bit, Windows and DOS |
| Pelles C IDE | 32-bit[1], Windows |
Usually both the assembler and the linker must be told that symbolic debugging information is to be generated ( with MS link, the linker option is /DEBUG ).
The -Zi option accepts an optional numeric argument to control the volume of information that is emitted. The values currently accepted are:
| 0 | Just global symbols will be written. |
| 1 | Global & local symbols will be written. No user-defined types are included. Usually this reduction does no harm, but may decrease linking time - if lots of modules are to be linked, the effect may be quite significant. |
| 2 | This is the default. Global & local symbols and user-defined types are written. |
| 3 | Additionally to 2, symbolic constants (equates) will be written. |
Also see OPTION CODEVIEW for additional switches to control symbolic debugging output.
| Option | Meaning |
|---|---|
| -zlf | suppresses the @file entry in the COFF symbol table. This entry is usually used for debugging purposes only and hence a - pretty small - amount of space can be saved. |
| -zlp | suppresses static (=private) procedures to be included into the COFF
symbol table - as long as they aren't referenced absolutely. Such procedures
aren't needed for the linking process. However, since the linker has no knowledge
of them then, they will also disappear from the linker-generated map-file. |
| -zls | suppresses the auxiliary entries for sections in the COFF symbol table. These entries may not be needed in all cases and thus a little space is saved. |
Option -zt0 will make object modules compatible to ALINK + Win32.lib. It may also ease adding assembly modules to Borland's C++Builder or Delphi projects.
The Microsoft FASTCALL convention uses registers AX, DX and BX in 16-bit for the first 3 parameters, and registers ECX and EDX in 32-bit for the first 2 parameters which are small enough to fit into a register.
The Open Watcom fastcall convention uses up to four registers ( E/AX, E/DX, E/BX, E/CX ).
In 64-bit mode, FASTCALL means the standard Windows 64 ABI if output format is not ELF. For -elf64, there is no FASTCALL support implemented yet.
To make FASTCALL the default calling convention, there are 3 ways:
Example using back quotes:
Module 1:
`functionname.with.dots` PROC C PUBLIC a1:dword
Module 2:
`functionname.with.dots` PROTO C :dword
.code
INVOKE `functionname.with.dots`, 1
Since IDs in back quotes are not 100% compatible with "normal" IDs, it might be considered to use the ALIAS directive instead. Be aware that, since the alias handling is a linker task, it is necessary to define both names, the alias name and the target name, as public.
mov eax, 1.0
With type coercion, it's also possible to define a 64-bit "double", although it's probably useful in 64-bit code only:
mov rax, real8 ptr 1.0
Additionally, operators LOW32 and HIGH32 accept a floating-point constant as argument. In this case, the constant is assumed to have format REAL8. Thus it's possible to pass a double constant directly as a procedure argument in 32-bit code:
push HIGH32 1.0
push LOW32 1.0
call WorkWithReal8Value
Example:
.386
.model flat, stdcall
option PROCALIGN:16
.code
proc1 PROC
ret
proc1 endp
proc2 PROC
ret
proc2 endp
end
The listing shows that start address of proc2 is aligned to 16 (=10h):
00000000 proc1 PROC 00000000 ret 00000000 C3 * retn 00000001 proc1 endp 00000010 proc2 PROC 00000010 ret 00000010 C3 * retn 00000011 proc2 endp
Note: to ensure that the procedures are aligned in the final binary as it is supposed by the OPTION PROCALIGN value, the alignment of the current code segment must be at least the value of OPTION PROCALIGN.
| start_fixups | offset within the header where segment fixups will start. The size of the header will always be at least this value, even if there are no fixups at all. Default - and minimum - value is 1Eh. |
| header_align | alignment of the header (including segment fixups). Value must be a power of 2, 10h is the default and minimum. |
| heap_min | the additional space (in paragraphs) which is needed by the binary to run. Default is the total of the sizes of the uninitialized BSS and STACK segments. |
| heap_max | space (in paragraphs) which the binary would like to have. Default is FFFFh. |
|
The unwind information which is generated is "complete", that is, it contains the ".endprologue" pseudo-op already. To allow to save all non-volatile registers in the prologue, the "USES" phrase is more capable in this mode and will accept XMM registers to be saved and restored.
push NULL
call DWORD PTR [_imp__GetModuleHandle@4]
code generation without OPTION DLLIMPORT:
push NULL
call _GetModuleHandle@4
...
_GetModuleHandle@4:
jmp DWORD PTR [_imp__GetModuleHandle@4] ;stub added by the linker
.386
.model flat,stdcall
option dllimport:<kernel32>
GetModuleHandleA proto :dword
ExitProcess proto :dword
option dllimport:none
.code
invoke GetModuleHandleA, 0
invoke ExitProcess, 0
end
There is currently only one switch :
option codeview:1
_TLS segment dword alias(".tls") public 'TLS'
tvar DD -1 ;codeview symbol tvar will be S_LTHREAD32
_TLS ends
OPTION STACKBASE will additionally define assembly-time variable @StackBase. The assembler will add the value of this variable to the effective address of stack variables. @StackBase can be modified just like any userdefined variable - however, it is initialized to zero by the PROC directive. The purpose for the introduction of @StackBase is to make it feasible to use the "volatile" stack-pointer (ESP/RSP) register as base for accessing stack variables.
Finally, OPTION STACKBASE will define another assembly-time variable: @ProcStatus. This variable is read-only and will allow to query information about the current procedure's status. The information that is returned by @ProcStatus is:
| Bit | Meaning if bit is 1 |
|---|---|
| 0 | inside prologue of current procedure. |
| 1 | inside epilogue of current procedure. |
| 2 | "frame-pointer omission" is on for procedure |
| 7 | prologue of current procedure isn't created yet |
Note: in JWasm v2.00-2.09, PUSHCONTEXT / POPCONTEXT ALL did include these alignment values. Since JWasm v2.10, this is no longer true; this behavior is more Masm-compatible.
The .X64 directive isn't needed usually, because for output formats WIN64 (see -win64) and ELF64 (see -elf64), .X64 is the default.
The .X64p directive is useful for mixed-model binaries or system software (see example DOS64 ).
When the cpu is set to 64-bit, the SEGMENT directive accepts a new 'size' value: USE64. It tells the assembler that this segment's offset is 64-bit wide and uses 64-bit instructions.
The SYSCALL calling convention is renamed to SYSCALL_ when 64-bit is on, because there exists a SYSCALL instruction mnemonic in this mode.
<macro_name> MACRO <param_name>:LABEL [,<param_name>[, ...]]
The LABEL attribute is accepted for the first parameter only. A macro with such a parameter can be invoked in the following way:
<label> <macro_name> [<argument>, ...]
Example:
foo macro lbl:LABEL, first, second
lbl db first
dw second
endm
.data
data1 foo 1,1000
data2 foo 2,2000
Note that a code label ( that is, a label followed by a colon or double-colon ) is parsed BEFORE the macro is evaluated, hence such a label will have been defined already when the macro "runs".
IFDEF <struct_name>.<member_name>
vmm1 MMWORD 1122334455667788h
vxmm1 XMMWORD 112233445566778899AABBCCDDEEFFh
Masm will accept just floating-point initializers for data items of type [X]MMWORD. It's even worse, since floating-point initializers are silently ignored for data items with sizes != 4, 8 and 10; since XMMWORD has size 16, it's impossible to initialize such an item directly. JWasm copies this Masm behavior, but to allow to initialize a XMMWORD with a floating-point value, one may use type coercion:
vxmm1 XMMWORD real4 ptr 1.0 ;bytes 4-15 will be 0
vxmm2 XMMWORD real8 ptr 1.0 ;bytes 8-15 will be 0
Variants that work in both JWasm and Masm, and also allow to initialize the full XMMWORD are:
vxmm1 LABEL XMMWORD
real4 1.0, 2.0, 3.0, 4.0
vxmm2 LABEL XMMWORD
real8 1.0, 2.0
myarray LABEL word : 10 ; myarray is assumed to be an array of 10 words
dw 1,2,3,4,5,6,7,8,9,10
Please note that the array size argument defines the array's number of elements, not the array's size in bytes.
This extension allows to define large initialized arrays, not restricted by line size limits. The SIZEOF and LENGTHOF operators will return the same values as if the array had been defined via the DUP operator.
The array size argument may be a forward reference:
myarray LABEL word : size_myarray / sizeof word
dw 1,2,3,4,5,6,7,8,9,10
size_myarray equ $ - myarray
segname SEGMENT COMDAT( selection [, assoc_segment ] ) ...
The selection argument tells the linker what to do if multiple definitions of a COMDAT symbol are found; the accepted values are:
| Value | Description | |
|---|---|---|
| 1 | no duplicates | If the symbol is already defined, the linker issues a "multiply defined symbol" error. |
| 2 | any | Any section that defines the same COMDAT symbol can be linked; the rest are removed. |
| 3 | same size | The linker chooses an arbitrary section among the definitions for this symbol. If all definitions are not the same size, a "multiply defined symbol" error is issued. |
| 4 | exact match | The linker chooses an arbitrary section among the definitions for this symbol. If all definitions do not match exactly, a "multiply defined symbol" error is issued. |
| 5 | associative | The section is linked if a certain other COMDAT section ( see the assoc_segment in the syntax description ) is linked. |
| 6 | largest | The linker chooses the largest definition from among all of the definitions for this symbol. If multiple definitions have this size, the choice between them is arbitrary. |
Currently support for COMDAT is restricted to COFF.
JWasm won't do anything special with COMDAT sections; in future releases this may change: cmdline options similar to the Microsoft VC compiler options -Gf or -Gy may be added.
To create an object module that places each function in its own COMDAT section ( as it is done by MS VC if the -Gy option is given ), it is recommended to use COMDAT in conjunction with ALIAS:
_TEXT_proc1 segment flat comdat(1) alias(".text")
proc1 proc c
...
proc1 endp
_TEXT1_proc1 ends
_TEXT_proc2 segment flat comdat(1) alias(".text")
proc2 proc c private
...
proc2 endp
_TEXT2_proc2 ends
_TEXT_proc3 segment flat comdat(1) alias(".text")
proc3 proc c
...
proc3 endp
_TEXT_proc3 ends
Also see Member Argument for IF[N]DEF and .ERR[N]DEF Directives.
Since Masm v8, a PROTO or EXTERNDEF for a symbol which is later defined as a PROC will make the procedure public, no matter what a possible visibility attribute of the PROC itself - or the default one set with OPTION PROC - is telling.
OTOH, with Masm v6/7, both the visibility attribute of the PROC directive and the current default setting of OPTION PROC will affect the symbol's visibility.
Masm6 Masm8 JWasm JWasm+Zv8
-------------------------------------
On,E,P x x
On,E,Pn x x
On,E,Pp x x x x
Op,E,P x x x x
Op,E,Pn x x x
Op,E,Pp x x x x
On = OPTION PROC:PRIVATE
Op = OPTION PROC:PUBLIC
E = PROTO or EXTERNDEF before PROC
P = PROC without visibility attribute
Pn = PROC with PRIVATE visibility attribute
Pp = PROC with PUBLIC visibility attribute
x = procedure will be public
As default, JWasm more or less copies the Masm v6/7 behavior. The
difference is that an explicite visibility attribute behind PROC has
the highest priority for JWasm. However, since v2.04, there's an
additional cmdline option -Zv8 which will make JWasm behave like Masm v8+.
It should be noted that without a PROTO/EXTERNDEF before PROC, there are no differences between Masm v6, v8 and JWasm, and the -Zv8 switch also has no effect then.
mov al, gs:[1000h]
mov al, gs:[100000000h]
If a constant address is to be accessed without segment prefixes - note that in 64-bit, only segment registers FS and GS can be used as segment prefixes - one has to use the FLAT keyword in JWasm:
mov al, FLAT:[1000h] ;invalid for Masm
mov al, FLAT:[100000000h] ;invalid for Masm
This syntax differs from Masm's, because Masm won't accept FLAT. In 64-bit Masm, the syntax for accessing constant addresses is instead:
mov al, [1000h] ;invalid for JWasm
mov al, [100000000h] ;invalid for JWasm
The code that will be generated won't show any differences:
0000000000000000: 65 8A 04 25 10 00 00 00 mov al,byte ptr gs:[00000010h] 0000000000000008: 65 A0 00 00 00 00 01 00 00 00 mov al,byte ptr gs:[0000000100000000h] 0000000000000012: 8A 04 25 10 00 00 00 mov al,byte ptr ds:[00000010h] 0000000000000019: A0 00 00 00 00 01 00 00 00 mov al,byte ptr ds:[0000000100000000h]
With Masm, SSE4.1 and SSE4.2 require Masm v9; AVX requires Masm v10.
For a few instructions, the encoding differs between Masm versions.
Example:
cmp al,dl
is encoded 38 D0 in Masm v6, but 3A C2 in Masm v8. In such cases, JWasm will prefer to copy the encoding of Masm v8.
Label1:
JMP Label2
Label2:
REPEAT Label2 - Label1
INC AX
ENDM
Masm will - incorrectly - repeat the loop 10 times, although the result of expression Label2 - Label1 is 2 only. OTOH, JWasm will repeat the loop 2 times only, because it's using an "optimistic" strategy concerning forward references.
| -omf | Intel's "relocatable Object Module Format", including 32-bit MS extensions. It's the default. |
| -coff | (MS) COFF object module format, supports flat memory models only. It's usually used for 32-bit Windows modules. |
| -elf | 32-Bit ELF ("Executable and Linkable Format") object modules. |
| -elf64 | 64-bit ELF object modules. |
| -win64 | 64-bit format for Win64 object modules. COFF variant with 64-bit extensions. |
| -djgpp | COFF variant used by DJGPP. Not active in precompiled binaries. |
| -bin | raw binary format. |
| -mz | DOS MZ binary format. |
| -pe | 32- and 64-bit PE binaries. |
| Type | Description | |
|---|---|---|
| THEADR | 1 | Marks the start of an object module, contains the name of the source file. |
| COMENT, class A1h | 1 | MS extension; tells linker the CodeView version number. Emitted if -Zi option is active. |
| COMENT, class E9h | n | Borland-style auto-dependency record(s). Emitted if -Zd or -Zi options are active. |
| COMENT, class 9Eh | 1 | MS extension; directs the linker to use a "standardized" segment ordering. Emitted if the .DOSSEG directive is found in the source. |
| COMENT, class 9Fh | n | Default library search name(s). Emitted if INCLUDELIB directives are used. |
| LNAMES | n | Defines names for segments and groups ( optionally also for externals, communals and publics ). |
| SEGDEF | n | Defines segment(s). |
| COMENT, class FEh | n | Tells WLink to do FARCALL optimization for a specific segment. Suppressed with -zld. |
| GRPDEF | n | Defines group(s). |
| EXTDEF | n | Defines external(s). |
| COMENT, class A8h | n | Defines weak external(s). Emitted if EXTERN directive is used with "altname". |
| COMDEF | n | Defines communal(s). |
| ALIAS | n | Defines alias(es). |
| PUBDEF | n | Defines public(s). |
| COMENT, class A0h | n | Defines export(s). Emitted if the EXPORT attribute is used in a PROC directive. |
| COMENT, class A2h | 1 | Link Pass Separator. Emitted if no entry point is defined in this object module. |
| LEDATA | n | Data record; defines segment content(s). |
| FIXUPP | n | Contains information to make the linker resolve references between object modules. |
| LINNUM | n | Line number information. Emitted if -Zd or -Zi option is active. |
| COMENT, class FDh | n | Tells disassembler that a code segment contains data. Suppressed with -zlc. |
| MODEND | 1 | Marks the end of the object module; optionally defines the entry point. |
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.
The binary format is most useful for bootloaders or DOS COM files, but may be used to create any binary format. See sample Win32_5, that demonstrates how the binary format is used to create a Win32 application.
If a listing file is produced, a binary map will be added, which shows the file and memory layout of the image:
.model tiny
.data
00000000 0D0A48656C6C6F2C20 str1 db 13,10,"Hello, world!",13,10,'$'
00000000 .code
org 100h
00000100 start:
00000100 B409 mov ah, 09h
00000102 BA0000 mov dx, offset str1
00000105 CD21 int 21h
00000107 B8004C mov ax, 4c00h
0000010A CD21 int 21h
end start
Binary Map:
Segment Pos(file) VA Size(fil) Size(mem)
---------------------------------------------------------------
_TEXT 0 100 C C
_DATA C 10C 12 12
---------------------------------------------------------------
1E 1E
Note that bytes with "undefined contents" at the start and the end of the output file are skipped and won't become part of the binary.
The PE format requires a .MODEL FLAT directive in the source code. This directive will trigger the creation of the internal PE-header section, the value of the cpu at this time will determine whether a 32- or 64-bit PE binary is to be written.
As in all binary formats, the listing will contain a binary map; see Binary Output Format for more details.
If -pe is set, a few sections will be created internally:
The default values in the PE header are
| Field | 32-bit Value | 64-bit Value (if different) |
|---|---|---|
| Signature | "PE" | |
| Machine | 14Ch | 8664h |
| Timestamp | date & time | |
| Size OptionalHeader | 0E0h | 0F0h |
| Characteristics | 10Fh | 12Fh |
| Magic | 10Bh | 20Bh |
| LinkerVersion | 5.1 | |
| ImageBase | 400000h | |
| SectionAlignment | 1000h | |
| FileAlignment | 200h | |
| OSVersion | 4.0 | |
| ImageVersion | 0.0 | |
| SubsystemVersion | 4.0 | |
| Win32Version | 0 | |
| Checksum | 0 | |
| Subsystem | 2 (=Console) | |
| DllCharacteristics | 0 | |
| SizeOfStack | 100000h,1000h | |
| SizeOfHeap | 100000h,1000h | |
| LoaderFlags | 0 |
To change the default values in the PE header there are two options. First, a predefined assembly-time variable @pe_file_flags will map the value of field Characteristics - changing the value of @pe_file_flags will also change the value in the header field. The other fields in the PE header are only accessible by setting the appropriate values in section .hdr$2. Fields not listed in the table above are set internally by the assembler to ensure data integrity and cannot be modified from within the assembly source.
If the PE binary is to use resources, a .rsrc section has to be created which is to contain them. Defining the resources manually works and is doable, but it might become tedious if a lot of resource items are to be defined. Therefore tool res2inc is supplied, which allows to convert a compiled resource file (.RES) to an assembly include file.
If a dll is created with -pe, one has to mark all procedures that are to be exported with the EXPORT attribute. If the exported names are to be undecorated, use the -zze cmdline option.
Sample Win64_8 shows how a 64-bit Windows binary is created with -pe. It also shows how to define resources in .rsrc manually and how to modify default values of PE header fields.
| # | Description | Fixed Masm Version |
|---|---|---|
| 1 | the infamous "invoke" bug: if an argument for invoke has to be expanded (from BYTE or WORD to DWORD, for example ), bad code was generated. | 9 |
| 2 | PROTOs contained twice in the source caused an EXTDEF entry to be generated in the object module. | - |
| 3 | "TYPE xmm0" will return 10 in Masm v6 and v7 - the correct value is 16. | 8 |
| 4 | a nested structure might cause a GPF in Masm if the embedded STRUCT's starting offset has to be adjusted due to alignment. | - |
| 5 | defining huge arrays in Masm is very slow and might even cause a deadlock if COFF has been selected as output format. | - |
| 6 | for Masm v6 and v7, if an array > 64 kB is defined and output format OMF is selected, the array's size will be mod 0x10000 only. | 8 |
| 7 | Masm doesn't flag invalid numbers in struct/array initializer strings. | - |
| 8 | if an ALIAS is defined somewhere in the source and the symbol table is listed, a 'General Failure' error occurs in Masm if output format is OMF. | - |
| 9 | Type "coerces" for DWORD data items defined in a 32bit segment are ignored by Masm, i.e., "dd far16 ptr <symbol>" will generate a near32 fixup instead of a far16 one. | - |
| 10 | if the ALIGN directive has to add 5 bytes in 32bit code segments, Masm includes an "add eax,0" opcode, which isn't a no-op because flags are modified. | - |
| 11 | silent truncation of immediate constants: Masm v6 and v7 will accept line "mov [word_variable],12345h" without error. | 8 |
| 12 | preprocessed output with option -EP may erroneously contain text macros and macro function calls if the macros are located in the initialization string of a structured variable. | - |
| 13 | Masm generates wrong code if a conditional jump is coupled with a type coercion which modifies offset magnitude. Examples: "jz near32 ptr ..." in 16bit code or "jz near16 ptr ..." in 32bit code). | - |
| 14 | if the arguments given to Masm end with an option which expects a parameter (i.e. "ml -c -Fo"), a 'General Failure' may occur. | - |
| 15 | floating-point data items in Masm can be followed by any suffix (example: REAL4 1.0foo, 2.0bar). JWasm won't accept this. | - |
| 16 | If a local is defined inside a macro, Masm will create a unique name for it. The name is constructed by using '??' as prefix, followed by a hexadecimal number with 4 digits. There is no check for overflow, however, so if the total of locals in all macros exceeds 65536, strange errors will occur. | - |
| 17 | If a weak external is defined for -coff with the ALIAS directive, an invalid fixup - and also a strange entry in the module's symbol table - is created. | - |
| 18 | If a section contains more than 0xffff relocations in COFF, the number of relocations that is stored in the object module is just the value of the lower 16-bit half of the relocation count. | 8 |
| 19 | If a symbolic constant (=equate) is made public in OMF format, Masm will store the symbol's value in a 16-bit record if it is in the range -32768 ... 65535. If the symbol is referenced in another module as a 32-bit number, it is always zero-extended, never sign-extended; hence values -1 ... -32768 will become 65535 ... 32768. | - |
| 20 | if data labels become public by the -Zf option ( and not by the PUBLIC directive ), their names are not decorated. Also, if format is COFF, they won't become true publics, they're just included in the symbol table with class "static", | - |
If there's ever a problem with one of the missing features, it's very likely that it's related to OPTION OLDMACROS. This option makes Masm 6 emulate two Masm 5.1 peculiarities:
This manual was written by Andreas Grech ( aka Japheth ).
It may be redistributed as long as it is free of charge.
|
|
|
|
|
|
|
|
;--- This sample shows how to use SEH primitives. It doesn't use hll
;--- directives. Thus this source can be assembled by both JWasm
;--- and Masm64.
;---
;--- to assemble enter:
;--- JWasm -win64 Win64_3.asm
;--- or:
;--- ml64 -c Win64_3.asm
;---
;--- to link the binary enter:
;--- Link Win64_3.obj
option casemap:none
includelib kernel32.lib
includelib user32.lib
HINSTANCE typedef QWORD
HWND typedef QWORD
HMENU typedef QWORD
HICON typedef QWORD
HBRUSH typedef QWORD
HCURSOR typedef QWORD
WPARAM typedef QWORD
LPARAM typedef QWORD
LPSTR typedef QWORD
LPVOID typedef QWORD
UINT typedef DWORD
NULL equ 0
WS_OVERLAPPEDWINDOW equ 0CF0000h
CW_USEDEFAULT equ 80000000h
SW_SHOWDEFAULT equ 10
SW_SHOWNORMAL equ 1
IDC_ARROW equ 32512
IDI_APPLICATION equ 32512
WM_DESTROY equ 2
CS_VREDRAW equ 1
CS_HREDRAW equ 2
COLOR_WINDOW equ 5
proto_WNDPROC typedef proto :HWND,:QWORD,:WPARAM,:LPARAM
WNDPROC typedef ptr proto_WNDPROC
WNDCLASSEXA struct 8
cbSize DWORD ?
style DWORD ?
lpfnWndProc WNDPROC ?
cbClsExtra DWORD ?
cbWndExtra DWORD ?
hInstance HINSTANCE ?
hIcon HICON ?
hCursor HCURSOR ?
hbrBackground HBRUSH ?
lpszMenuName LPSTR ?
lpszClassName LPSTR ?
hIconSm HICON ?
WNDCLASSEXA ends
POINT struct
x SDWORD ?
y SDWORD ?
POINT ends
MSG struct 8
hwnd HWND ?
message DWORD ?
wParam WPARAM ?
lParam LPARAM ?
time DWORD ?
pt POINT <>
MSG ends
GetModuleHandleA proto :LPSTR
GetCommandLineA proto
ExitProcess proto :UINT
LoadIconA proto :HINSTANCE, :LPSTR
LoadCursorA proto :HINSTANCE, :LPSTR
RegisterClassExA proto :ptr WNDCLASSEXA
CreateWindowExA proto :DWORD, :LPSTR, :LPSTR, :DWORD, :SDWORD, :SDWORD, :SDWORD, :SDWORD, :HWND, :HMENU, :HINSTANCE, :LPVOID
ShowWindow proto :HWND, :SDWORD
UpdateWindow proto :HWND
GetMessageA proto :ptr MSG, :HWND, :SDWORD, :SDWORD
TranslateMessage proto :ptr MSG
DispatchMessageA proto :ptr MSG
PostQuitMessage proto :SDWORD
DefWindowProcA proto :HWND, :UINT, :WPARAM, :LPARAM
;WinMain proto :HINSTANCE, :HINSTANCE, :LPSTR, :UINT
.data
ClassName db "SimpleWinClass",0
AppName db "Our First Window",0
.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?
.code
WinMainCRTStartup proc FRAME
push rbp
.pushreg rbp
mov rbp,rsp
.setframe rbp, 0
.endprolog
sub rsp,32
mov ecx,NULL
call GetModuleHandleA
mov hInstance, rax
call GetCommandLineA
mov CommandLine, rax
mov rcx, hInstance
mov rdx, NULL
mov r8, CommandLine
mov r9d, SW_SHOWDEFAULT
call WinMain
mov ecx, eax
call ExitProcess
align 4
WinMainCRTStartup endp
WinMain proc FRAME
push rbp
.pushreg rbp
mov rbp,rsp
.setframe rbp, 0
.endprolog
sub rsp, sizeof WNDCLASSEXA + sizeof MSG + sizeof HWND + 12*8
hInst equ <[rbp+10h]>
hPrevInst equ <[rbp+18h]>
CmdLine equ <[rbp+20h]>
CmdShow equ <[rbp+28h]>
wc equ <[rbp - sizeof WNDCLASSEXA].WNDCLASSEXA>
msg equ <[rbp - sizeof WNDCLASSEXA - sizeof MSG].MSG>
hwnd equ <[rbp - sizeof WNDCLASSEXA - sizeof MSG - sizeof HWND]>
mov hInst, rcx ;store param1 in shadow space
mov wc.cbSize, SIZEOF WNDCLASSEXA
mov wc.style, CS_HREDRAW or CS_VREDRAW
; mov rax, OFFSET WndProc ;using LEA is preferable
lea rax, [WndProc]
mov wc.lpfnWndProc, rax
mov wc.cbClsExtra, NULL
mov wc.cbWndExtra, NULL
mov wc.hInstance, rcx
mov wc.hbrBackground, COLOR_WINDOW+1
mov wc.lpszMenuName, NULL
; mov rax, OFFSET ClassName ;using LEA is preferable
lea rax, [ClassName]
mov wc.lpszClassName, rax
mov ecx, NULL
mov edx, IDI_APPLICATION
call LoadIconA
mov wc.hIcon, rax
mov wc.hIconSm, rax
mov ecx, NULL
mov edx, IDC_ARROW
call LoadCursorA
mov wc.hCursor,rax
lea rcx, wc
call RegisterClassExA
mov ecx, NULL
lea rdx, [ClassName]
lea r8, [AppName]
mov r9d, WS_OVERLAPPEDWINDOW
mov dword ptr [rsp+4*8], CW_USEDEFAULT
mov dword ptr [rsp+5*8], CW_USEDEFAULT
mov dword ptr [rsp+6*8], CW_USEDEFAULT
mov dword ptr [rsp+7*8], CW_USEDEFAULT
mov qword ptr [rsp+8*8], NULL
mov qword ptr [rsp+9*8], NULL
mov rax, hInst
mov [rsp+10*8], rax
mov qword ptr [rsp+11*8], NULL
call CreateWindowExA
mov hwnd,rax
mov rcx, hwnd
mov edx, SW_SHOWNORMAL
call ShowWindow
mov rcx, hwnd
call UpdateWindow
;--- message loop
@@:
lea rcx, msg
mov rdx, NULL
mov r8, 0
mov r9, 0
call GetMessageA
and rax, rax
jz @F
lea rcx, msg
call TranslateMessage
lea rcx, msg
call DispatchMessageA
jmp @B
@@:
mov rax, msg.wParam
add rsp, sizeof WNDCLASSEXA + sizeof MSG + sizeof HWND + 12*8
pop rbp
ret
align 4
WinMain endp
WndProc proc FRAME
sub rsp, 4*8
.allocstack 4*8
.endprolog
cmp edx, WM_DESTROY
jnz @F
mov ecx, NULL
call PostQuitMessage
xor rax,rax
jmp exit
@@:
call DefWindowProcA
exit:
add rsp, 4*8
ret
align 4
WndProc endp
end
|
;--- SEH support in Win64. Unlike Win64_3,
;--- this version uses hll directives, so it cannot be assembled
;--- with Masm64. Also, OPTION FRAME:AUTO is used.
;---
;--- to create the binary enter:
;--- JWasm -win64 Win64_3e.asm
;--- Link Win64_3e.obj
option casemap:none
option frame:auto ;generate SEH-compatible prologues and epilogues
includelib kernel32.lib
includelib user32.lib
HINSTANCE typedef QWORD
HWND typedef QWORD
HMENU typedef QWORD
HICON typedef QWORD
HBRUSH typedef QWORD
HCURSOR typedef QWORD
WPARAM typedef QWORD
LPARAM typedef QWORD
LPSTR typedef QWORD
LPVOID typedef QWORD
UINT typedef DWORD
NULL equ 0
WS_OVERLAPPEDWINDOW equ 0CF0000h
CW_USEDEFAULT equ 80000000h
SW_SHOWDEFAULT equ 10
SW_SHOWNORMAL equ 1
IDC_ARROW equ 32512
IDI_APPLICATION equ 32512
WM_DESTROY equ 2
CS_VREDRAW equ 1
CS_HREDRAW equ 2
COLOR_WINDOW equ 5
proto_WNDPROC typedef proto :HWND,:QWORD,:WPARAM,:LPARAM
WNDPROC typedef ptr proto_WNDPROC
WNDCLASSEXA struct 8
cbSize DWORD ?
style DWORD ?
lpfnWndProc WNDPROC ?
cbClsExtra DWORD ?
cbWndExtra DWORD ?
hInstance HINSTANCE ?
hIcon HICON ?
hCursor HCURSOR ?
hbrBackground HBRUSH ?
lpszMenuName LPSTR ?
lpszClassName LPSTR ?
hIconSm HICON ?
WNDCLASSEXA ends
POINT struct
x SDWORD ?
y SDWORD ?
POINT ends
MSG struct 8
hwnd HWND ?
message DWORD ?
wParam WPARAM ?
lParam LPARAM ?
time DWORD ?
pt POINT <>
MSG ends
GetModuleHandleA proto :LPSTR
GetCommandLineA proto
ExitProcess proto :UINT
LoadIconA proto :HINSTANCE, :LPSTR
LoadCursorA proto :HINSTANCE, :LPSTR
RegisterClassExA proto :ptr WNDCLASSEXA
CreateWindowExA proto :DWORD, :LPSTR, :LPSTR, :DWORD, :SDWORD, :SDWORD, :SDWORD, :SDWORD, :HWND, :HMENU, :HINSTANCE, :LPVOID
ShowWindow proto :HWND, :SDWORD
UpdateWindow proto :HWND
GetMessageA proto :ptr MSG, :HWND, :SDWORD, :SDWORD
TranslateMessage proto :ptr MSG
DispatchMessageA proto :ptr MSG
PostQuitMessage proto :SDWORD
DefWindowProcA proto :HWND, :UINT, :WPARAM, :LPARAM
WinMain proto :HINSTANCE, :HINSTANCE, :LPSTR, :UINT
.data
ClassName db "SimpleWinClass",0
AppName db "Our First Window",0
.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?
.code
WinMainCRTStartup proc FRAME
invoke GetModuleHandleA, NULL
mov hInstance, rax
invoke GetCommandLineA
mov CommandLine, rax
invoke WinMain, hInstance, NULL, CommandLine, SW_SHOWDEFAULT
invoke ExitProcess, eax
WinMainCRTStartup endp
WinMain proc FRAME hInst:HINSTANCE, hPrevInst:HINSTANCE, CmdLine:LPSTR, CmdShow:UINT
local wc:WNDCLASSEXA
local msg:MSG
local hwnd:HWND
mov hInst, rcx
mov wc.cbSize, SIZEOF WNDCLASSEXA
mov wc.style, CS_HREDRAW or CS_VREDRAW
lea rax, [WndProc]
mov wc.lpfnWndProc, rax
mov wc.cbClsExtra, NULL
mov wc.cbWndExtra, NULL
mov wc.hInstance, rcx
mov wc.hbrBackground, COLOR_WINDOW+1
mov wc.lpszMenuName, NULL
lea rax, [ClassName]
mov wc.lpszClassName, rax
invoke LoadIconA, NULL, IDI_APPLICATION
mov wc.hIcon, rax
mov wc.hIconSm, rax
invoke LoadCursorA, NULL, IDC_ARROW
mov wc.hCursor,rax
invoke RegisterClassExA, addr wc
invoke CreateWindowExA, NULL, ADDR ClassName, ADDR AppName,\
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,\
CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, NULL, NULL,\
hInst, NULL
mov hwnd,rax
invoke ShowWindow, hwnd, SW_SHOWNORMAL
invoke UpdateWindow, hwnd
.while (1)
invoke GetMessageA, ADDR msg, NULL, 0, 0
.break .if (!rax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessageA, ADDR msg
.endw
mov rax, msg.wParam
ret
WinMain endp
WndProc proc FRAME hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.if ( edx == WM_DESTROY )
invoke PostQuitMessage, NULL
xor rax,rax
.else
invoke DefWindowProcA, rcx, edx, r8, r9
.endif
ret
WndProc endp
end WinMainCRTStartup
|
;--- DOS program which switches to long-mode and back.
;--- Note: requires at least JWasm v2.
;--- Also: needs a 64bit cpu in real-mode to run.
;--- Parts of the source are based on samples supplied by
;--- sinsi and Tomasz Grysztar in the FASM forum.
;--- To create the binary enter:
;--- JWasm -mz DOS64.asm
.x64p
;--- 16bit start/exit code
_TEXT16 segment use16 para public 'CODE'
assume ds:_TEXT16
assume es:_TEXT16
GDTR label fword ; Global Descriptors Table Register
dw 4*8-1 ; limit of GDT (size minus one)
dd offset GDT ; linear address of GDT
IDTR label fword ; Interrupt Descriptor Table Register
dw 256*16-1 ; limit of IDT (size minus one)
dd 0 ; linear address of IDT
nullidt label fword
dw 3FFh
dd 0
align 8
GDT dq 0 ; null descriptor
dw 0FFFFh,0,9A00h,0AFh ; 64-bit code descriptor
dw 0FFFFh,0,9A00h,000h ; compatibility mode code descriptor
dw 0FFFFh,0,9200h,000h ; compatibility mode data descriptor
wPICMask dw 0 ; variable to save/restore PIC masks
start16:
push cs
pop ds
mov ax,cs
movzx eax,ax
shl eax,4
add dword ptr [GDTR+2], eax ; convert offset to linear address
mov word ptr [GDT+2*8+2], ax
mov word ptr [GDT+3*8+2], ax
shr eax,16
mov byte ptr [GDT+2*8+4], al
mov byte ptr [GDT+3*8+4], al
mov ax,ss
mov dx,es
sub ax,dx
mov bx,sp
shr bx,4
add bx,ax
mov ah,4Ah
int 21h ; free unused memory
push cs
pop es
mov ax,ss
mov dx,cs
sub ax,dx
shl ax,4
add ax,sp
push ds
pop ss
mov sp,ax ; make a TINY model, CS=SS=DS=ES
smsw ax
test al,1
jz @F
mov dx,offset err1
mov ah,9
int 21h
mov ah,4Ch
int 21h
err1 db "Mode is V86. Need REAL mode to switch to LONG mode!",13,10,'$'
@@:
xor edx,edx
mov eax,80000001h ; test if long-mode is supported
cpuid
test edx,20000000h
jnz @F
mov dx,offset err2
mov ah,9
int 21h
mov ah,4Ch
int 21h
err2 db "No 64bit cpu detected.",13,10,'$'
@@:
mov bx,1000h
mov ah,48h
int 21h
jnc @F
mov dx,offset err3
mov ah,9
int 21h
mov ah,4Ch
int 21h
err3 db "Out of memory",13,10,'$'
@@:
add ax,100h-1 ; align to page boundary
mov al,0
mov es,ax
;--- setup page directories and tables
sub di,di
mov cx,4096
sub eax,eax
rep stosd ; clear 4 pages
sub di,di
mov ax,es
movzx eax,ax
shl eax,4
mov cr3,eax ; load page-map level-4 base
lea edx, [eax+5000h]
mov dword ptr [IDTR+2], edx
or eax,111b
add eax, 1000h
mov es:[di+0000h],eax ; first PDP table
add eax, 1000h
mov es:[di+1000h],eax ; first page directory
add eax, 1000h
mov es:[di+2000h],eax ; first page table
mov di,3000h ; address of first page table
mov eax,0 + 111b
mov cx,256 ; number of pages to map (1 MB)
@@:
stosd
add di,4
add eax,1000h
loop @B
;--- setup ebx/rbx with linear address of _TEXT
mov bx,_TEXT
movzx ebx,bx
shl ebx,4
add [llg], ebx
;--- create IDT
mov di,5000h
mov cx,32
mov edx, offset exception
add edx, ebx
make_exc_gates:
mov eax,edx
stosw
mov ax,8
stosw
mov ax,8E00h
stosd
xor eax, eax
stosd
stosd
add edx,4
loop make_exc_gates
mov cx,256-32
make_int_gates:
mov eax,offset interrupt
add eax, ebx
stosw
mov ax,8
stosw
mov ax,8E00h
stosd
xor eax, eax
stosd
stosd
loop make_int_gates
mov di,5000h
mov eax, ebx
add eax, offset clock
mov es:[di+80h*16+0],ax ; set IRQ 0 handler
shr eax,16
mov es:[di+80h*16+6],ax
mov eax, ebx
add eax, offset keyboard
mov es:[di+81h*16+0],ax ; set IRQ 1 handler
shr eax,16
mov es:[di+81h*16+6],ax
;--- clear NT flag
pushf
pop ax
and ah,0BFh
push ax
popf
;--- reprogram PIC: change IRQ 0-7 to INT 80h-87h, IRQ 8-15 to INT 88h-8Fh
cli
in al,0A1h
mov ah,al
in al,21h
mov [wPICMask],ax
mov al,10001b ; begin PIC 1 initialization
out 20h,al
mov al,10001b ; begin PIC 2 initialization
out 0A0h,al
mov al,80h ; IRQ 0-7: interrupts 80h-87h
out 21h,al
mov al,88h ; IRQ 8-15: interrupts 88h-8Fh
out 0A1h,al
mov al,100b ; slave connected to IRQ2
out 21h,al
mov al,2
out 0A1h,al
mov al,1 ; Intel environment, manual EOI
out 21h,al
out 0A1h,al
in al,21h
mov al,11111100b ; enable only clock and keyboard IRQ
out 21h,al
in al,0A1h
mov al,11111111b
out 0A1h,al
mov eax,cr4
or eax,1 shl 5
mov cr4,eax ; enable physical-address extensions (PAE)
mov ecx,0C0000080h ; EFER MSR
rdmsr
or eax,1 shl 8 ; enable long mode
wrmsr
lgdt [GDTR]
lidt [IDTR]
mov cx,ss
movzx ecx,cx ; get base of SS
shl ecx,4
movzx esp,sp
add ecx, esp ; ECX=linear address of current SS:ESP
mov eax,cr0
or eax,80000001h
mov cr0,eax ; enable paging + pmode
db 66h, 0EAh ; jmp 0008:oooooooo
llg dd offset long_start
dw 8
;--- switch back to real-mode and exit
backtoreal:
cli
mov eax,cr0
and eax,7FFFFFFFh ; disable paging
mov cr0,eax
mov ecx,0C0000080h ; EFER MSR
rdmsr
and ah,not 1h ; disable long mode (EFER.LME=0)
wrmsr
mov ax,24 ; set SS,DS and ES to 64k data
mov ss,ax
mov ds,ax
mov es,ax
mov eax,cr0 ; switch to real mode
and al,0FEh
mov cr0, eax
db 0eah ; clear instruction cache, CS=real-mode seg
dw $+4
dw _TEXT16
mov ax,STACK ; SS=real-mode seg
mov ss, ax
mov sp,4096
push cs ; DS=real-mode _TEXT16 seg
pop ds
lidt [nullidt] ; IDTR=real-mode compatible values
mov eax,cr4
and al,not 20h ; disable physical-address extensions (PAE)
mov cr4,eax
;--- reprogram PIC: change IRQ 0-7 to INT 08h-0Fh, IRQ 8-15 to INT 70h-77h
mov al,10001b ; begin PIC 1 initialization
out 20h,al
mov al,10001b ; begin PIC 2 initialization
out 0A0h,al
mov al,08h ; IRQ 0-7: back to ints 8h-Fh
out 21h,al
mov al,70h ; IRQ 8-15: back to ints 70h-77h
out 0A1h,al
mov al,100b ; slave connected to IRQ2
out 21h,al
mov al,2
out 0A1h,al
mov al,1 ; Intel environment, manual EOI
out 21h,al
out 0A1h,al
in al,21h
mov ax,[wPICMask] ; restore PIC masks
out 21h,al
mov al,ah
out 0A1h,al
sti
mov ax,4c00h
int 21h
_TEXT16 ends
;--- here's the 64bit code segment.
;--- since 64bit code is always flat but the DOS mz format is segmented,
;--- there are restrictions, because the assembler doesn't know the
;--- linear address where the 64bit segment will be loaded:
;--- + direct addressing with constants isn't possible (mov [0B8000h],rax)
;--- since the rip-relative address will be calculated wrong.
;--- + 64bit offsets (mov rax, offset <var>) must be adjusted by the linear
;--- address where the 64bit segment was loaded (is in rbx).
;---
;--- rbx must preserve linear address of _TEXT
_TEXT segment para use64 public 'CODE'
assume ds:FLAT, es:FLAT
long_start:
xor eax,eax
mov ss,eax
mov esp,ecx
sti ; now interrupts can be used
call WriteStrX
db "Hello 64bit",10,0
nextcmd:
mov r8b,0 ; r8b will be filled by the keyboard irq routine
nocmd:
cmp r8b,0
jz nocmd
cmp r8b,1 ; ESC?
jz esc_pressed
cmp r8b,13h ; 'r'?
jz r_pressed
call WriteStrX
db "unknown key ",0
mov al,r8b
call WriteB
call WriteStrX
db 10,0
jmp nextcmd
;--- 'r' key: display some register contents
r_pressed:
call WriteStrX
db 10,"cr0=",0
mov rax,cr0
call WriteQW
call WriteStrX
db 10,"cr2=",0
mov rax,cr2
call WriteQW
call WriteStrX
db 10,"cr3=",0
mov rax,cr3
call WriteQW
call WriteStrX
db 10,"cr4=",0
mov rax,cr4
call WriteQW
call WriteStrX
db 10,"cr8=",0
mov rax,cr8
call WriteQW
call WriteStrX
db 10,0
jmp nextcmd
;--- ESC: back to real-mode
esc_pressed:
jmp [bv]
bv label fword
dd offset backtoreal
dw 16
;--- screen output helpers
;--- scroll screen up one line
;--- rsi = linear address start of last line
;--- rbp = linear address of BIOS area (0x400)
scroll_screen:
cld
mov edi,esi
movzx eax,word ptr [rbp+4Ah]
push rax
lea rsi, [rsi+2*rax]
mov cl, [rbp+84h]
mul cl
mov ecx,eax
rep movsw
pop rcx
mov ax,0720h
rep stosw
ret
WriteChr:
push rbp
push rdi
push rsi
push rbx
push rcx
push rdx
push rax
mov edi,0B8000h
mov ebp,400h
cmp byte ptr [rbp+63h],0B4h
jnz @F
xor di,di
@@:
movzx ebx, word ptr [rbp+4Eh]
add edi, ebx
movzx ebx, byte ptr [rbp+62h]
mov esi, edi
movzx ecx, byte ptr [rbx*2+rbp+50h+1] ;ROW
movzx eax, word ptr [rbp+4Ah]
mul ecx
movzx edx, byte ptr [rbx*2+rbp+50h] ;COL
add eax, edx
mov dh,cl
lea edi, [rdi+rax*2]
mov al, [rsp]
cmp al, 10
jz newline
mov [rdi], al
mov byte ptr [rdi+1], 07
inc dl
cmp dl, byte ptr [rbp+4Ah]
jb @F
newline:
mov dl, 00
inc dh
cmp dh, byte ptr [rbp+84h]
jbe @F
dec dh
call scroll_screen
@@:
mov [rbx*2+rbp+50h],dx
pop rax
pop rdx
pop rcx
pop rbx
pop rsi
pop rdi
pop rbp
ret
WriteStr: ;write string in rdx
push rsi
mov rsi, rdx
cld
@@:
lodsb
and al,al
jz @F
call WriteChr
jmp @B
@@:
pop rsi
ret
WriteStrX: ;write string at rip
push rsi
mov rsi, [rsp+8]
cld
@@:
lodsb
and al,al
jz @F
call WriteChr
jmp @B
@@:
mov [rsp+8],rsi
pop rsi
ret
WriteQW: ;write QWord in rax
push rax
shr rax,32
call WriteDW
pop rax
WriteDW:
push rax
shr rax,16
call WriteW
pop rax
WriteW:
push rax
shr rax,8
call WriteB
pop rax
WriteB: ;write Byte in al
push rax
shr rax,4
call WriteNb
pop rax
WriteNb:
and al,0Fh
add al,'0'
cmp al,'9'
jbe @F
add al,7
@@:
jmp WriteChr
;--- exception handler
exception:
excno = 0
repeat 32
push excno
jmp @F
excno = excno+1
endm
@@:
call WriteStrX
db 10,"Exception ",0
pop rax
call WriteB
call WriteStrX
db " errcode=",0
mov rax,[rsp+0]
call WriteQW
call WriteStrX
db " rip=",0
mov rax,[rsp+8]
call WriteQW
call WriteStrX
db 10,0
@@:
jmp $
;--- clock and keyboard interrupts
clock:
push rbp
mov ebp,400h
inc dword ptr [rbp+6Ch]
pop rbp
interrupt: ; handler for all other interrupts
push rax
mov al,20h
out 20h,al
pop rax
iretq
keyboard:
push rax
in al,60h
test al,80h
jnz @F
mov r8b, al
@@:
in al,61h ; give finishing information
out 61h,al ; to keyboard...
mov al,20h
out 20h,al ; ...and interrupt controller
pop rax
iretq
_TEXT ends
;--- 4k stack, used in both modes
STACK segment use16 para stack 'STACK'
db 4096 dup (?)
STACK ends
end start16
|
;--- Win32 "hello world" console application.
;--- Uses JWasm's bin output format, so no linker needed.
;--- assemble: JWasm -bin -Fo Win32_5.exe Win32_5.ASM
.386
option casemap:none
.nolist
include winnt.inc ;include PE image definitions
.list
STD_OUTPUT_HANDLE equ -11
IMAGEBASE equ 400000h
PEHDR segment dword FLAT
;--- define the DOS "MZ" header
org IMAGEBASE
IMAGE_DOS_HEADER <"ZM", 80h, 1, 0,4,0,-1,0,200h,0,0,0,0,0,<0>,0,0,<0>,IMAGEREL PEHdr>
db 0Eh ;push cs
db 1Fh ;pop ds
db 0BAh,0Eh,0 ;mov dx,text
db 0B4h,09h ;mov ah,9
db 0CDh,21h ;int 21h
db 0B8h,01h,4Ch;mov ax,4c01h
db 0CDh,21h ;int 21h
db "This program cannot be run in DOS mode",13,10,'$'
org IMAGEBASE+80h
;--- define the Win32 "PE" header
PEHdr label byte
db "PE",0,0
IMAGE_FILE_HEADER <IMAGE_FILE_MACHINE_I386, num_sections, 0, 0, 0, sizeof IMAGE_OPTIONAL_HEADER32,
IMAGE_FILE_RELOCS_STRIPPED or IMAGE_FILE_EXECUTABLE_IMAGE or IMAGE_FILE_32BIT_MACHINE or IMAGE_FILE_LOCAL_SYMS_STRIPPED>
IMAGE_OPTIONAL_HEADER32 { 10Bh, ;magic
6,0, ;linker major, minor
1000h,1000h,0, ;sizeof code, initialized data, uninitialized data
IMAGEREL mainCRTStartup, ;entry point
IMAGEREL start_text, IMAGEREL start_rdata, ;baseof code, data
IMAGEBASE, ;imagebase
1000h,200h, ;section alignment, file alignment
4,0, ;OS major, minor
0,0, ;Image major, minor
4,0, ;Subsys major, minor
0, ;win32 version
3000h, ;sizeof image
1000h, ;sizeof header
0, ;checksum
IMAGE_SUBSYSTEM_WINDOWS_CUI,
0, ;dll characteristics
100000h,1000h,;stack res,com
100000h,1000h,;heap res, com
0, ;loader flags
16, ;number of directories
<<0,0>, ;exports
< IMAGEREL start_idata, SECTIONREL endof_idata >, ;imports
<0,0>,<0,0>, ;resource, exception
<>,<>,<>,<>, ;security, baserelocs, debug, architecture
<>,<>,<>,<>, ;globalptr, tls, load_config, bound_import
<>,<>,<>,<>>} ;iat, delay_import, com descriptor, reserved
;--- define the section table
sectiontable label byte
IMAGE_SECTION_HEADER <".text", <sizeof_text>, IMAGEREL start_text, sizeof_text,
200h, 0, 0, 0, 0, 060000020h >
IMAGE_SECTION_HEADER <".rdata", <SECTIONREL endof_idata + sizeof_const>, IMAGEREL start_rdata, SECTIONREL endof_idata + sizeof_const,
400h, 0, 0, 0, 0, 040000040h >
num_sections equ ( $ - sectiontable ) / sizeof IMAGE_SECTION_HEADER
org IMAGEBASE+200h ;forces physical size of header to 200h and sets VA to 400200h
PEHDR ends
;--- the ALIGNx segments are needed because
;--- section alignment and file alignment are different
ALIGN1 segment dword public FLAT 'DATA'
org 0E00h ; change pc to RVA 1000h
ALIGN1 ends
_TEXT segment dword public FLAT 'CODE'
_TEXT ends
ALIGN2 segment dword public FLAT 'DATA'
org 0E00h ; change pc to RVA 2000h
ALIGN2 ends
_IDATA segment dword public FLAT 'DATA'
start_rdata label byte
start_idata label byte
;--- import descriptors go here
_IDATA ends
_IDATA$1 segment dword public FLAT 'DATA'
IMAGE_IMPORT_DESCRIPTOR <<0>,0,0,0,0>
;--- ILT entries go here
_IDATA$1 ends
_IDATA$2 segment dword public FLAT 'DATA'
dd 0 ;--- end of last ILT
;--- IAT entries go here
_IDATA$2 ends
_IDATA$3 segment dword public FLAT 'DATA'
dd 0 ;--- end of last IAT
;--- import name strings go here
_IDATA$3 ends
_IDATA$4 segment dword public FLAT 'DATA'
endof_idata equ $
_IDATA$4 ends
CONST segment dword public FLAT 'DATA'
start_const label byte
CONST ends
DefineImpDll macro name
_IDATA segment
IMAGE_IMPORT_DESCRIPTOR <<IMAGEREL name&ILT>,0,0,IMAGEREL name, IMAGEREL name&IAT>
_IDATA ends
_IDATA$1 segment
ifdef ImportDefined
dd 0 ;terminate previous ILT
endif
name&ILT label dword
_IDATA$1 ends
_IDATA$2 segment
ifdef ImportDefined
dd 0 ;terminate previous IAT
endif
name&IAT label dword
_IDATA$2 ends
_IDATA$3 segment
name db @CatStr(!",name, !"),0
align 4
_IDATA$3 ends
ImportDefined equ 1
endm
DefineImport macro name
_IDATA$1 segment
dd IMAGEREL n&name
_IDATA$1 ends
_IDATA$2 segment
lp&name typedef ptr pr&name
name lp&name IMAGEREL n&name
_IDATA$2 ends
_IDATA$3 segment
n&name dw 0
db @CatStr(!",name, !"),0
align 4
_IDATA$3 ends
endm
prWriteConsoleA typedef proto stdcall :dword, :dword, :dword, :dword, :dword
prGetStdHandle typedef proto stdcall :dword
prExitProcess typedef proto stdcall :dword
DefineImpDll kernel32
DefineImport ExitProcess
DefineImport WriteConsoleA
DefineImport GetStdHandle
if 0 ;if further dlls are to be imported
prMessageBoxA typedef proto stdcall :dword, :dword, :dword, :dword
DefineImpDll user32
DefineImport MessageBoxA
endif
CONST segment
string db 13,10,"hello, world.",13,10
sizeof_const equ $ - start_const
CONST ends
_TEXT segment
assume ds:FLAT,es:FLAT
start_text label near
;--- start of program
main proc
local dwWritten:dword
local hConsole:dword
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov hConsole,eax
invoke WriteConsoleA, hConsole, addr string, sizeof string, addr dwWritten, 0
xor eax,eax
ret
main endp
;--- entry
mainCRTStartup proc c
invoke main
invoke ExitProcess, eax
mainCRTStartup endp
sizeof_text equ $ - start_text
org 200h ;align size of _TEXT to next 512 byte boundary
_TEXT ends
end
|
;--- Win32_7 - Shows how to use OPTION DLLIMPORT and switch -Fd.
;--- No import libraries are needed in the link step.
;---
;--- assemble: JWasm -coff -Fd Win32_7.ASM
;--- link: JWlink format windows pe f Win32_7.OBJ
.386
.model FLAT, stdcall
option casemap:none
STD_OUTPUT_HANDLE equ -11
option dllimport:<kernel32>
WriteConsoleA proto :dword, :dword, :dword, :dword, :dword
GetStdHandle proto :dword
ExitProcess proto :dword
option dllimport:<user32>
MessageBoxA proto :dword, :dword, :dword, :dword
option dllimport:<none>
.const
msg db 13,10,"hello, world.",13,10
db 0
.code
main proc
local written:dword
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov ebx, eax
invoke WriteConsoleA, ebx, addr msg, sizeof msg,
addr written, 0
invoke MessageBoxA, 0, addr msg, 0, 0
ret
main endp
;--- entry
start:
invoke main
invoke ExitProcess, 0
end start
|
;--- create a 64-bit binary with -pe cmdline option
;---
;--- JWasm -pe Win64_8.asm
.x64 ; -pe requires to set cpu, model & language
.model flat, fastcall
option casemap:none
option frame:auto ; generate SEH-compatible prologues and epilogues
option win64:3 ; init shadow space, reserve stack at PROC level
;--- resource IDs
IDR_MENU1 equ 100
IDR_BITMAP1 equ 101
IDM_EXIT equ 1000
NULL equ 0
LPSTR typedef ptr
LPVOID typedef ptr
UINT typedef dword
BOOL typedef dword
;--- winbase definitions
HINSTANCE typedef ptr
;--- winuser definitions
HWND typedef ptr
HMENU typedef ptr
HICON typedef ptr
HBRUSH typedef ptr
HCURSOR typedef ptr
HDC typedef ptr
HBITMAP typedef ptr
WPARAM typedef ptr
LPARAM typedef qword
WS_OVERLAPPEDWINDOW equ 0CF0000h
CW_USEDEFAULT equ 80000000h
SW_SHOWDEFAULT equ 10
SW_SHOWNORMAL equ 1
IDC_ARROW equ 32512
IDI_APPLICATION equ 32512
CS_VREDRAW equ 1
CS_HREDRAW equ 2
COLOR_WINDOW equ 5
WM_DESTROY equ 2
WM_PAINT equ 000Fh
WM_COMMAND equ 0111h
proto_WNDPROC typedef proto :HWND,:qword,:WPARAM,:LPARAM
WNDPROC typedef ptr proto_WNDPROC
WNDCLASSEXA struct 8
cbSize dword ?
style dword ?
lpfnWndProc WNDPROC ?
cbClsExtra dword ?
cbWndExtra dword ?
hInstance HINSTANCE ?
hIcon HICON ?
hCursor HCURSOR ?
hbrBackground HBRUSH ?
lpszMenuName LPSTR ?
lpszClassName LPSTR ?
hIconSm HICON ?
WNDCLASSEXA ends
POINT struct
x sdword ?
y sdword ?
POINT ends
MSG struct 8
hwnd HWND ?
message dword ?
wParam WPARAM ?
lParam LPARAM ?
time dword ?
pt POINT <>
MSG ends
RECT struct
left sdword ?
top sdword ?
right sdword ?
bottom sdword ?
RECT ends
PAINTSTRUCT struct 8
hdc HDC ?
fErase BOOL ?
rcPaint RECT <>
fRestore BOOL ?
fIncUpdate BOOL ?
rgbReserved byte 32 dup (?)
PAINTSTRUCT ends
;--- wingdi definitions
DIB_RGB_COLORS equ 0
SRCCOPY equ 00CC0020h
HGDIOBJ typedef ptr
BITMAPINFOHEADER struct
biSize dword ?
biWidth sdword ?
biHeight sdword ?
biPlanes word ?
biBitCount word ?
biCompression dword ?
biSizeImage dword ?
biXPelsPerMeter sdword ?
biYPelsPerMeter sdword ?
biClrUsed dword ?
biClrImportant dword ?
BITMAPINFOHEADER ends
option dllimport:<kernel32>
GetModuleHandleA proto :LPSTR
GetCommandLineA proto
ExitProcess proto :UINT
option dllimport:<user32>
BeginPaint proto :HWND, :ptr PAINTSTRUCT
CreateWindowExA proto :dword, :LPSTR, :LPSTR, :dword, :sdword, :sdword, :sdword, :sdword, :HWND, :HMENU, :HINSTANCE, :LPVOID
DefWindowProcA proto :HWND, :UINT, :WPARAM, :LPARAM
DestroyWindow proto :HWND
DispatchMessageA proto :ptr MSG
EndPaint proto :HWND, :ptr PAINTSTRUCT
GetClientRect proto :HWND, :ptr RECT
GetMessageA proto :ptr MSG, :HWND, :sdword, :sdword
LoadBitmapA proto :HINSTANCE, :LPSTR
LoadCursorA proto :HINSTANCE, :LPSTR
LoadIconA proto :HINSTANCE, :LPSTR
PostQuitMessage proto :sdword
RegisterClassExA proto :ptr WNDCLASSEXA
ShowWindow proto :HWND, :sdword
TranslateMessage proto :ptr MSG
UpdateWindow proto :HWND
option DLLIMPORT:<gdi32>
BitBlt proto :HDC, :dword, :dword, :dword, :dword, :HDC, :dword, :dword, :dword
CreateCompatibleDC proto :HDC
DeleteDC proto :HDC
GetDIBits proto :HDC, :HBITMAP, :dword, :dword, :ptr, :ptr BITMAPINFO, :dword
SelectObject proto :HDC, :HGDIOBJ
option dllimport:none
WinMain proto :HINSTANCE, :HINSTANCE, :LPSTR, :UINT
.data
ClassName db "SimpleWinClass",0
AppName db "Bitmap rendering",0
.data?
hInstance HINSTANCE ?
hBitmap HBITMAP ?
CommandLine LPSTR ?
.code
WinMainCRTStartup proc FRAME
invoke GetModuleHandleA, NULL
mov hInstance, rax
invoke GetCommandLineA
mov CommandLine, rax
invoke WinMain, hInstance, NULL, CommandLine, SW_SHOWDEFAULT
invoke ExitProcess, eax
WinMainCRTStartup endp
WinMain proc FRAME hInst:HINSTANCE, hPrevInst:HINSTANCE, CmdLine:LPSTR, CmdShow:UINT
local wc:WNDCLASSEXA
local msg:MSG
local hwnd:HWND
invoke LoadBitmapA, hInst, IDR_BITMAP1
mov hBitmap, rax
mov wc.cbSize, sizeof WNDCLASSEXA
mov wc.style, CS_HREDRAW or CS_VREDRAW
lea rax, [WndProc]
mov wc.lpfnWndProc, rax
mov wc.cbClsExtra, NULL
mov wc.cbWndExtra, NULL
mov rcx, hInst
mov wc.hInstance, rcx
mov wc.hbrBackground, COLOR_WINDOW+1
mov wc.lpszMenuName, IDR_MENU1
lea rax, [ClassName]
mov wc.lpszClassName, rax
invoke LoadIconA, NULL, IDI_APPLICATION
mov wc.hIcon, rax
mov wc.hIconSm, rax
invoke LoadCursorA, NULL, IDC_ARROW
mov wc.hCursor,rax
invoke RegisterClassExA, addr wc
invoke CreateWindowExA, NULL, ADDR ClassName, ADDR AppName,
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, NULL, NULL,
hInst, NULL
mov hwnd,rax
invoke ShowWindow, hwnd, SW_SHOWNORMAL
invoke UpdateWindow, hwnd
.while (1)
invoke GetMessageA, ADDR msg, NULL, 0, 0
.break .if (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessageA, ADDR msg
.endw
mov rax, msg.wParam
ret
WinMain endp
WndProc proc FRAME hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
local hdc2:HDC
local ps:PAINTSTRUCT
local rect:RECT
local bmi:BITMAPINFOHEADER
.if edx == WM_DESTROY
invoke PostQuitMessage, NULL
xor rax,rax
.elseif edx == WM_COMMAND
.if wParam == IDM_EXIT
invoke DestroyWindow, hWnd
.endif
xor eax, eax
.elseif edx == WM_PAINT
invoke BeginPaint, hWnd, addr ps
invoke CreateCompatibleDC, ps.hdc
mov hdc2, rax
invoke SelectObject, hdc2, hBitmap
mov bmi.biSize, sizeof BITMAPINFOHEADER
mov bmi.biBitCount, 0
invoke GetDIBits, hdc2, hBitmap, 0, 0, 0, addr bmi, DIB_RGB_COLORS
invoke GetClientRect, hWnd, addr rect
mov r8d, rect.right
sub r8d, bmi.biWidth
jnc @F
xor r8d, r8d
@@:
shr r8d, 1
mov r9d, rect.bottom
sub r9d, bmi.biHeight
jnc @F
xor r9d, r9d
@@:
shr r9d, 1
invoke BitBlt, ps.hdc, r8d, r9d, bmi.biWidth, bmi.biHeight, hdc2, 0, 0, SRCCOPY
invoke DeleteDC, hdc2
invoke EndPaint, hWnd, addr ps
xor eax,eax
.else
invoke DefWindowProcA, rcx, edx, r8, r9
.endif
ret
WndProc endp
if 1 ;for -pe
RT_BITMAP equ 2
RT_MENU equ 4
;--- menu resource flags
MF_POPUP equ 10h
MF_END equ 80h
IMAGE_RESOURCE_DIRECTORY struct
Characteristics dword ?
TimeDateStamp dword ?
MajorVersion word ?
MinorVersion word ?
NumberOfNamedEntries word ?
NumberOfIdEntries word ?
IMAGE_RESOURCE_DIRECTORY ends
IMAGE_RESOURCE_DIRECTORY_ENTRY struct
union
r0 record NameIsString:1, NameOffset:31
Name_ dword ?
Id word ?
ends
union
OffsetToData dword ?
r1 record DataIsDirectory:1, OffsetToDirectory:31
ends
IMAGE_RESOURCE_DIRECTORY_ENTRY ends
IMAGE_RESOURCE_DATA_ENTRY struct
OffsetToData dword ?
Size_ dword ?
CodePage dword ?
Reserved dword ?
IMAGE_RESOURCE_DATA_ENTRY ends
option dotname
.rsrc segment dword FLAT public read 'RSRC'
;--- define menu IDR_MENU1 and bitmap IDR_BITMAP1
;--- root level: enum the resource types
IMAGE_RESOURCE_DIRECTORY <0,0,0,0,0,2>
IMAGE_RESOURCE_DIRECTORY_ENTRY < <RT_BITMAP>, <SECTIONREL bms + 80000000h> >
IMAGE_RESOURCE_DIRECTORY_ENTRY < <RT_MENU>, <SECTIONREL menus + 80000000h> >
;--- second level: enum the IDs of resource type X
bms IMAGE_RESOURCE_DIRECTORY <0,0,0,0,0,1>
IMAGE_RESOURCE_DIRECTORY_ENTRY < <IDR_BITMAP1>, <SECTIONREL bm1 + 80000000h> >
menus IMAGE_RESOURCE_DIRECTORY <0,0,0,0,0,1>
IMAGE_RESOURCE_DIRECTORY_ENTRY < <IDR_MENU1>, <SECTIONREL menu1 + 80000000h> >
;--- third level: enum the languages of ID X
bm1 IMAGE_RESOURCE_DIRECTORY <0,0,0,0,0,1>
IMAGE_RESOURCE_DIRECTORY_ENTRY < <409h>, <SECTIONREL bm1_l1> >
menu1 IMAGE_RESOURCE_DIRECTORY <0,0,0,0,0,1>
IMAGE_RESOURCE_DIRECTORY_ENTRY < <409h>, <SECTIONREL m1_l1> >
;--- last level: define the resource data
;--- data for menu IDR_MENU1, language 409h
m1_l1 IMAGE_RESOURCE_DATA_ENTRY <IMAGEREL m1_l1_data, size_m1_l1, 0, 0>
m1_l1_data dw 0,0 ;menu header
dw MF_POPUP or MF_END, '&','F','i','l','e',0
dw MF_END, IDM_EXIT, 'E','&','x','i','t',0
size_m1_l1 equ $ - m1_l1_data
align 4
;--- data for bitmap IDR_BITMAP1
bm1_l1 IMAGE_RESOURCE_DATA_ENTRY <IMAGEREL bm1_l1_data, size_bm1_l1, 0, 0>
bm1_l1_data label word
incbin <Win32_8.bmp>,14 ;skip bitmap file header
size_bm1_l1 equ $ - ( bm1_l1_data )
.rsrc ends
;--- set /subsystem:windows
;--- the PE header is stored in section .hdr$2
option dotname
.hdr$2 segment dword FLAT public 'HDR'
org 5Ch ;position to IMAGE_NT_HEADER64.OptionalHeader.Subsystem
dw 2 ;2=subsystem windows
.hdr$2 ends
endif
end WinMainCRTStartup
|
| x029 | Multiple base registers not allowed | In 16-bit code, one cannot use both BX and BP in indirect addressing; in 32/64-bit code, ESP/RSP can only appear once in indirect addressing. | |
| x030 | Instruction or register not accepted in current CPU mode | ||
| x031 | Invalid addressing mode with current CPU setting | ||
| x032 | Cannot use TRn-TRn with current CPU setting | The TRx special registers were restricted to 80386 and 80486 cpus. | |
| x033 | Must be index or base register | ||
| x034 | Multiple index registers not allowed | ||
| x035 | |||
| x036 | Scale factor must be 1, 2, 4 or 8 | ||
| x037 | Cannot be used as index register: <register> | Index registers are restricted. In 16-bit mode, only SI and DI can be index registers. In 32-bit mode, all general-purpose registers except ESP can be index registers. | |
| x038 | Base and index register differ in size | ||
| x039 | Expecting comma | ||
| x040 | ORG needs a constant or local offset | ||
| x041 | POP CS is not allowed | ||
| x042 | Only MOV can use special register | The special registers CRx, DRx and TRx can only be moved to/from general purpose registers. | |
| x043 | Cannot use SHORT with CALL | Distance of CALL operands must be NEAR or FAR. | |
| x044 | Only SHORT jump distance is allowed | Some jump instructions accept short distances only (JCXZ, JECXZ, LOOPx). | |
| x045 | Syntax error | ||
| x046 | Prefix must be followed by an instruction | ||
| x047 | Syntax error: Unexpected colon | ||
| x048 | Operands must be the same size: <size op1> - <size op2> | ||
| x049 | Invalid instruction operands | ||
| x050 | Jump distance not possible in current CPU mode | Jcc instructions won't accept type coercions that increase the jump distance (i.e. "jz NEAR PTR label") if current cpu is < 80386. | |
| x051 | Immediate data out of range | ||
| x052 | Can not use short or near modifiers with this instruction | ||
| x053 | Jump out of range by <num> byte(s) | A short distance must be in the range -128 to +127. | |
| x054 | Displacement out of range: <displacement> | ||
| x055 | Initializer value too large | ||
| x056 | Symbol already defined: <symbol> | ||
| x057 | Offset magnitude too large for specified size | ||
| x058 | Magnitude of offset exceeds 16 bit | ||
| x059 | Operand 2 too big | ||
| x060 | Operand 1 too small | ||
| x061 | Line too long | Size of a line ( after concatenation) is restricted to 600. | |
| x062 | Too many tokens in a line | The number of tokens in a line is restricted to 150. | |
| x063 | |||
| x064 | Operand is expected | ||
| x065 | Constant expected | A constant (numeric) value is expected in the current context. Note that a label - more exactly: the offset part of a label's address - is not a constant value, since the final value is calculated by the linker ( or the OS loader ) only. | |
| x066 | Constant operand is expected | The expression evaluator accepts a constant only in the current context. | |
| x067 | .ELSE clause already occured in this .IF block | An .IF block may contain 0 or 1 .ELSE clauses and it must be the last clause before .ENDIF. | |
| x068 | Multiple overrides | ||
| x069 | Segment, group or segment register expected | The operand before the colon operator (:) must be a segment, group or segment register. | |
| x070 | Identifier too long | Identifer names are restricted to 247. This is a hard limit for OMF output format. For other formats, the limit may be extended by adjusting and recompiling the source code. | |
| x071 | Invalid operand size for instruction | ||
| x072 | Not supported: <directive> | Message is displayed if one of the follwing options is specified: OPTION READONLY, OPTION EXPR16, OPTION OLDMACROS. Those are currently not supported. | |
| x073 | Size not specified, assuming: <type> | this is a warning. <type> may be BYTE, WORD or DWORD. The message may occur if an
immediate value is written to an untyped memory reference:
mov [ebx], 1
JWasm makes a guess and displays the warning, while Masm will display an error in such cases. |
|
| x074 | Floating-point initializer ignored | ||
| x075 | Only SHORT and NEAR jump distance is allowed | Conditional jump (Jcc) instruction destination cannot be far. | |
| x076 | Initializer magnitude too large for specified size | ||
| x077 | Segment attribute is defined already: <attribute> | ||
| x078 | Segment definition changed: %s, %s | ||
| x079 | Class name too long | Segment class names are restricted to 255 in size. | |
| x080 | Block nesting error: %s | ||
| x081 | Segment attribute is unknown: %s | ||
| x082 | Must be in segment block | Instructions and directives that generate code or data must be inside a segment block. | |
| x083 | Segment not defined: <segment> | ||
| x084 | Colon is expected | ||
| x085 | Invalid qualified type: %s | ||
| x086 | Qualified type is expected | ||
| x087 | |||
| x088 | Library name is missing | ||
| x089 | Cannot access label through segment registers: <label> | ||
| x090 | Line too long after expansion: <line> | ||
| x091 | Language type must be specified | ||
| x092 | PROC, MACRO or macro loop directive must precede LOCAL | ||
| x093 | Cannot nest procedures | ||
| x094 | VARARG requires C calling convention | ||
| x095 | Multiple .MODEL directives, .MODEL ignored | ||
| x096 | Model is not declared | Without a model, simplified segment directives ( .CODE, .DATA, .CONST, .DATA?, .STACK, .FARDATA and .FARDATA? ) and directives .STARTUP, .EXIT cannot be used. | |
| x097 | Backquote missing: `<identifier> | ||
| x098 | COMMENT delimiter expected | ||
| x099 | END directive required at end of file | ||
| x100 | Nesting level too deep | ||
| x101 | Macro nesting level too deep | ||
| x102 | Symbol not defined : <symbol> | ||
| x103 | |||
| x104 | No filename specified. | ||
| x105 | Out of Memory | This is a fatal error. With the 8086-version of jwasm, JWASMR, you'll see this error if you try to assemble something that contains a few thousand symbols. The 32- or 64-bit versions of jwasm should always have enough memory on modern machines. | |
| x106 | Cannot open file: "<file>" [<error code>] | Error code ENOENT means "file not found". Other error codes are displayed as numbers | |
| x107 | Cannot close file: <file> [<error code>] | ||
| x108 | File write error: <file> [<error code>] | Usually happens if output media is read-only or full. | |
| x109 | Invalid command-line option: <option> | ||
| x110 | Internal error in <source file>(<line>) | This error shouldn't be seen in the release version. It's displayed if the internal assert() function is called, which usually is done when a "virtually impossible" error condition has occurred. | |
| x111 | Expecting closing square bracket | ||
| x112 | Expecting file name | ||
| x113 | Too many errors | Use commandline option -e to set the max. number of errors that are displayed | |
| x114 | forced error <message> | Generic "forced error" message | |
| x115 | forced error: Value not equal to 0: <value> <text> | Error emitted by the .ERRNZ directive. | |
| x116 | forced error: Value equal to 0: <value> <text> | Error emitted by the .ERRE directive. | |
| x117 | forced error: symbol defined: <symbol> | Error emitted by the .ERRDEF directive. | |
| x118 | forced error: symbol not defined: <symbol> | Error emitted by the .ERRNDEF directive. | |
| x119 | forced error: string blank : <string> | Error emitted by the .ERRB directive. | |
| x120 | forced error: string not blank : <string> | Error emitted by the .ERRNB directive. | |
| x121 | forced error: strings not equal : <string> : <string> | Error emitted by the .ERRDIF and .ERRDIFI directives. | |
| x122 | forced error: strings equal : <string> : <string> | Error emitted by the .ERRIDN and .ERRIDNI directives. | |
| x123 | <file>(<line>): Included by | Additional error information if error occured in an include file. | |
| x124 | <file>(<line>)[<macro>]: Macro called from | Additional error information if error occured inside a macro. | |
| x125 | <file>(<line>): iteration <iteration>: Macro called from | Additional error information if error occured inside a loop macro (FOR, FORC, REPEAT, ...). | |
| x126 | <file>(<line>): Main line code | Additional error information if error occured inside an include file or a macro. | |
| x127 | Extending jump | ||
| x128 | Directive ignored: %s | ||
| x129 | number must be a power of 2 | ||
| x130 | Incompatible with segment alignment: %s | ||
| x131 | Segment expected: %s | ||
| x132 | Incompatible CPU mode for 32-bit segment | ||
| x133 | Far call is converted to near call. | ||
| x134 | CPU option %s is not valid for selected CPU. | ||
| x135 | Segment '%s' is in another group already | ||
| x136 | Symbol type conflict: %s | ||
| x137 | Conflicting parameter definition: %s | ||
| x138 | PROC and PROTO calling convention conflict | ||
| x139 | Non-benign %s redefinition: %s | ||
| x140 | Too many bits in RECORD: %s | ||
| x141 | Statement not allowed inside structure definition | ||
| x142 | Unmatched block nesting: %s | ||
| x143 | Symbol redefinition: %s | ||
| x144 | Text item required | ||
| x145 | INVOKE argument type mismatch: argument %u | ||
| x146 | Too few arguments to INVOKE: %s | ||
| x147 | VARARG parameter must be last | ||
| x148 | LABEL parameter must be first | ||
| x149 | Too many arguments in macro call: %s | This is a warning. Macro is invoked with more arguments than expected. | |
| x150 | Missing operator in expression | ||
| x151 | Unexpected literal found in expression: %s | Literals enclosed in <> or {} are items processed by the preprocessor or to initialize "structured" data items. If they're used otherwise, this error will occur. | |
| x152 | Initializer must be a string or single item: %s | ||
| x153 | Too many initial values for structure: %s | ||
| x154 | Too many initial values for array: %s | ||
| x155 | String or text literal too long | ||
| x156 | PROLOGUE must be macro function | The user-defined prologue macro must be a macro function, that is, there must be an EXITM somewhere inside that returns a literal. | |
| x157 | EPILOGUE must be macro procedure: %s | The user-defined epilogue macro must be a macro procedure, that is, there must NOT be an EXITM somewhere inside that returns a literal. | |
| x158 | Reserved word expected | ||
| x159 | INVOKE requires prototype for procedure | ||
| x160 | Invalid type for data declaration: %s | ||
| x161 | Operand must be RECORD type or field | ||
| x162 | Unmatched macro nesting | ||
| x163 | Empty (null) string | ||
| x164 | No segment information to create fixup: %s | ||
| x165 | Register value overwritten by INVOKE | ||
| x166 | Missing quotation mark in string | ||
| x167 | Divide by zero in expression | ||
| x168 | General Failure | ||
| x169 | Cannot have implicit far jump or call to near label | ||
| x170 | Invalid use of register | ||
| x171 | Distance invalid for current segment | ||
| x172 | Initializer magnitude too large: %s | ||
| x173 | Cannot add two relocatable labels | ||
| x174 | Cannot define as public or external: <symbol_name> | Text macros, macros, stack variables, structure fields or segment/groups cannot be public or external. | |
| x175 | Positive value expected | ||
| x176 | FAR not allowed in FLAT model COMM variables | ||
| x177 | Too many arguments to INVOKE | ||
| x178 | Directive must appear inside a macro | ||
| x179 | Invalid type expression | ||
| x180 | Cannot declare scoped code label as PUBLIC: <label> | ||
| x181 | Invalid radix tag | ||
| x182 | Instruction operand must have size | The instruction allows operands with more than just one size, and the wanted size cannot be guessed from the current operands. | |
| x183 | Use of register assumed to ERROR | ||
| x184 | Instructions and initialized data not supported in <seg_type> segments | <seg_type> may be BSS or AT. Such segments don't have data. | |
| x185 | Literal expected after '=' | ||
| x186 | No 4k Page-aligned segments in MS386 OMF | A 4K page-aligned segment isn't compatible with MS OMF format, it's a Phar Lab extension. This warning won't appear in the standard version. | |
| x187 | |||
| x188 | Operand must be relocatable | ||
| x189 | Constant or relocatable label expected | ||
| x190 | [ELSE]IF2/.ERR2 not allowed, single-pass assembler | ||
| x191 | Expression too complex for UNTILCXZ | ||
| x192 | Operands must be in same segment | ||
| x193 | Invalid use of external symbol: <symbol_name> | ||
| x194 | For -coff leading underscore required for start label: <start_label> | ||
| x195 | Invalid command-line value, default is used: %s | ||
| x196 | Unknown fixup type: %u at <segment>.<offset> | ||
| x197 | Unsupported fixup type for <format>: <type> | ||
| x198 | Invalid fixup type for <format> <type> at location <segment>.<offset> | ||
| x199 | Syntax error in control-flow directive | ||
| x200 | Invalid .model parameter for flat model | ||
| x201 | Output format doesn't support externals: <symbol> | In formats BIN and MZ all references must be local to the module. | |
| x202 | Invalid start label for -bin | ||
| x203 | No start label defined | Warning, format MZ only: MZ-binaries usually have a start label. In some cases (i.e. overlays) a missing start label may be ok. | |
| x204 | No stack defined | Warning, format MZ only: MZ-binaries usually have a stack. In some cases (i.e. overlays) a missing stack may be ok. | |
| x205 | Invalid alignment - value must be 2^n (n=4..15) | ||
| x206 | Index value past end of string: <value> | The index argument of SUBSTR or INSTR is beyond the string argument length | |
| x207 | Count value too large | ||
| x208 | Count must be positive or zero | ||
| x209 | Syntax error: <item> | The parser found an item that has no meaning in the current context | |
| x210 | |||
| x211 | |||
| x212 | Must use floating-point initializer | ||
| x213 | ORG directive not allowed in unions | ||
| x214 | Struct alignment must be 1, 2, 4, 8, 16 or 32 | ||
| x215 | Structure cannot be instanced | A structure that has size 0 or that contains an ORG directive cannot be instanced. | |
| x216 | Missing angle bracket or brace in literal | ||
| x217 | Nondigit in number: <number> | ||
| x218 | 16bit fixup for 32bit label: %s | ||
| x219 | Too many macro placeholders | The number of parameters and locals for a macro must not exceed 256 | |
| x220 | Missing macro argument: %s, parameter %u | ||
| x221 | Doesn't work with 32-bit segments: <directive> | Directives .STARTUP and .EXIT work for 16-bit only. | |
| x222 | Segment exceeds 64k limit: %s | In MZ format, 16-bit segments are restricted to 64k. | |
| x223 | Not supported with OMF format: %s | ||
| x224 | Not supported with current output format: %s | The directive or feature isn't supported by all formats. For example, segment-related directives or attributes won't make much sense for flat formats like COFF or ELF. | |
| x225 | Unknown default prologue argument: %s | ||
| x226 | LOADDS ignored in flat model | ||
| x227 | Missing right parenthesis in expression | ||
| x228 | Invalid operand for <operator>: <operand> | ||
| x229 | Structure improperly initialized: %s | ||
| x230 | Expected: %s | ||
| x231 | Invalid data initializer | ||
| x232 | Expected data label | Some operators ( LENGTH, SIZE ) work with data labels only. | |
| x233 | Expression must be a code address | ||
| x234 | -n Option needs a valid name parameter | ||
| x235 | Constant value too large: <value> | the value of the constant doesn't fit in 64 or - if it is a number to be assigned to a symbolic constant - 32 bits. | |
| x236 | Text macro was used before definition | this is a warning only. However, using text macros before they have been defined will force JWasm to do a full second pass, which increases assembly time. | |
| x237 | Offset size incompatible with current segment | ||
| x238 | Instruction form requires 80386 | ||
| x239 | Group/Segment offset size conflict: <group offset> - <segment offset> | Segments within a group must all have the same offset size. | |
| x240 | Assembly passes reached: <passes> | Although this is a warning only it usually indicates a severe problem. The assembler is very probably unable to calculate "final" values of all labels and has to be terminated by pressing Ctrl-C. | |
| x241 | Filename parameter must be enclosed in <> or quotes | The INCBIN directive requires delimiters for its filename. | |
| x242 | Start address on END directive ignored with .STARTUP | ||
| x243 | Invalid symbol type in expression: <symbol> | The expression evaluator has encountered a symbol that is meaningless in expressions, for example a (text) macro. | |
| x244 | Missing right parenthesis | ||
| x245 | Directive must be in control block | .ELSE, .ELSEIF and .ENDIF are valid inside .IF-blocks, .BREAK, .CONTINUE may occur inside .WHILE- or .REPEAT-blocks, .ENDW needs a preceding .WHILE and .UNTIL needs a preceding .REPEAT. | |
| x246 | Expected: memory model | the .MODEL directive needs at least one parameter, the memory model. | |
| x247 | Type is wrong size for register | ||
| x248 | IF[n]DEF expects a plain symbol as argument | this is a warning. Masm accepts any expression as argument for directives [ELSE]IF[N]DEF, but the result probably isn't always what has been expected. | |
| x249 | Jump destination must specify a label | ||
| x250 | Ignored: <attribute> | An attribute or parameter of a directive was found, but not handled. See Known Bugs and missing Features for details about what features aren't implemented yet. | |
| x251 | Missing argument for cmdline option | ||
| x252 | Invalid coprocessor register | ||
| x253 | Registers AH-DH may not be used with SPL-DIL or R8-R15 | 64-bit only. | |
| x254 | .ENDPROLOG found before EH directives | 64-bit only. | |
| x255 | Missing FRAME in PROC, no unwind code will be generated | 64-bit only. | |
| x256 | Bad alignment for offset in unwind code | 64-bit only. | |
| x257 | Nonzero value expected | ||
| x258 | Size of prolog too big, must be < 256 bytes | 64-bit only. | |
| x259 | Missing .ENDPROLOG: %s | 64-bit only. | |
| x260 | .SAFESEH argument must be a PROC | ||
| x261 | Directive ignored without -%s switch | ||
| x262 | ELF GNU extensions (8/16-bit relocations) used | This is a warning only. The extensions are not "official", but the GNU linker LD will understand them. | |
| x263 | Syntax error in expression | ||
| x264 | Macro label not defined: %s | The target of a GOTO must be within the very same macro. | |
| x265 | Procedure argument or local not referenced: %s | This warning is displayed only if at least -W3 is specified. | |
| x266 | Group definition too large, truncated: <group_name> | The size of the OMF record that is to define a group would exceed 4 kB. However, to see this error you'll have to define a group that is to comprise more than 1000 segments, | |
| x267 | COMM variable exceeds 64K: <variable> | in 16-bit, the size of a COMM variable is restricted to 64 kB. | |
| x268 | Must be public or external: %s | Names that are to be known by the linker must be public or external. | |
| x269 | parameter/local name is reserved word: %s | This is a warning. The names of macro parameters or locals have highest priority and hence the reserved word will become inaccessible within the macro. | |
| x270 | real or BCD number not allowed | ||
| x271 | structure field expected | ||
| x272 | Constant value too large: <value> | the value of the constant doesn't fit in 64 or - if it is a number to be assigned to a symbolic constant - 32 bits. | |
| x273 | ELSE clause already occured in this IF block | An IF block may contain 0 or 1 ELSE clauses and it must be the last clause before ENDIF. | |
| x274 | Illegal use of segment register | ||
| x275 | Group exceeds 64K: <group> | MZ format only: a group that contains 16-bit segments cannot be larger than 64 kB, because the group must fit into a physical segment. | |
| x276 | EXPORT must be FAR: <symbol> | A 16-bit procedure that is to be exported must be declared with the FAR distance attribute. |
ml.exe -c *.asmto assemble all assembly files in a directory won't work as expected.
The debug version offers the following additional commandline options:
| -af | Display all files used in assembly process |
| -ce | Cause an exception |
| -dm | Display all messages |
| -dr | Display reserved words |
| -drh | Display reserved words hash table |
| -ds | Display global symbols |
| -dsh | Display global symbols hash table |
| -dt | Display debug trace |
| -ls | Display preprocessed line storage |
| -nbp | Disable back-patching |
| -nfp | Do full subsequent passes ( disables "fastpass" ) |
| -pm=<n> | Stop assembly after n passes |
| -sp | Skip preprocessor step |