Critiques from a TASM user (John Burger 19 March 2014)
NASM has some advantages over Borland's TASM (or TASM32 for running on 64-bt Windows), but a number of disadvantages which can lead to dangerous code:
- TASM is closed source, and will only run on Microsoft operating systems. NASM is open and portable.
- TASM only understands mnemonics up to around the Pentium Pro. NASM understands all of them.
- TASM can only produce OBJ files, which need to be linked into a final binary with a separate linker. NASM can also produce OBJ files, along with a number of other intermediate formats, but it can also produce final binary forms such as BIN, COM and even EXE (with a hack), obviating the need for a linker.
- NASM has a really neat structure definition syntax, meaning that you don't need to worry about structure fields being globally defined. In TASM and NASM, the following definition 'pollutes' the global namespace:
STRUC Point X RESW 1 Y RESW 1 ENDSTRUC
After this definition, X and Y are forevermore defined. For unambiguity, you are forced to change your names to something like:
STRUC Point Pt_X RESW 1 Pt_Y RESW 1 ENDSTRUC
But, NASM offers a solution: by leveraging the '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]
Personally, I'd prefer the following for the last lines - but NASM doesn't keep the type of variables so that cannot work:
MOV AX,[Cursor.X] MOV DX,[Cursor.Y]
- There is no type safety at all. If you define a variable
Variable DW 1234h
then later accesses still don't know what size it is. The following will produce an 'Unknown size' error:
The solution is that you MUST provide an override. But what if you provide the wrong one?
MOV [Variable],EAX MOV DWORD PTR [Variable],12345678h
It will assemble fine, and your code will overwrite adjacent memory.
- There is no mechanism for structures within structures. If you define a Point structure:
STRUC Point .X RESW 1 .Y RESW 1 ENDSTRUC
then there is no mechanism to include that structure within another one. Only fundamental types are allowed.
- There is no mechanism for bitfields, with their attendant
In short, they've provided a basic assembler with VERY powerful macro features - but their fundamental assumption that types are 'not important' allow the programmer using it to make very dangerous code.
Note that the NASMX project addresses some of these shortfalls (in particular the nested
STRUC one) with some very sophisticated macros. Using this though defines practically a whole new language, necessitating the religious use of their macros over the fundamental types defined by the assembler.