NASM is by far the most ported assembler for the x86 architecture - it's available for practically every Operating System based on the x86 (even being included with MacOS), and is available as a cross-platform assembler on other platforms.
This assembler uses Intel syntax, but it is different from others because it focuses heavily on its own "macro" language - this permits the programmer to build up more complex expressions using simpler definitions, allowing new "instructions" to be created.
Unfortunately this powerful feature comes at a cost: the type of the data gets in the way of generalised instructions, so data typing is not enforced.
response: db 'Y' ; Character that user typed
cmp response, 'N' ; *** Error! Unknown size!
cmp byte response, 'N' ; That's better!
cmp response, ax ; No error!
However, NASM introduced one feature that others lacked: scoped symbol names. When you define a symbol in other assemblers, that name is available throughout the rest of the code - but that "uses up" that name, "polluting" the global name space with symbols.
For example (using NASM syntax):
STRUC Point
X resw 1
Y resw 1
ENDSTRUC
After this definition, X and Y are forevermore defined. To avoid "using up" the names X
and Y
, you needed to use more definite names:
STRUC Point
Pt_X resw 1
Pt_Y resw 1
ENDSTRUC
But NASM offers an alternative. By leveraging its "local variable" concept, you can define structure fields that require you to nominate the containing structure in future references:
STRUC Point
.X resw 1
.Y resw 1
ENDSTRUC
Cursor ISTRUC Point
ENDISTRUC
mov ax,[Cursor+Point.X]
mov dx,[Cursor+Point.Y]
Unfortunately, because NASM doesn't keep track of types, you can't use the more natural syntax:
mov ax,[Cursor.X]
mov dx,[Cursor.Y]