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
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]