User:Johnburger/NASMCritique

From OSDev Wiki
Jump to navigation Jump to search

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:

Pros

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

Cons

  • 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:

         MOV           [Variable],5678h

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 WIDTH, MASK and SHIFT operators.

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.