- 2.3.13. -
Table of Contents
2. TMT Pascal Language Description
2.3. Built-in Assembler
2.3.13. Differences between 16- and 32-bit code
2.3.13. Differences between 16- and 32-bit
code
While this manual does not really teach 32-bit assembly programming,
we will list here several considerations important in 32-bit assembler
programming. These considerations may be helpful to a 16-bit programmer
entering the 32-bit arena.
Avoid using 16-bit registers for indexation
The built-in assembler will correctly assemble instructions like
MOV BX,offset table
MOV AX,table[BX]
JMP table[BX]
However, these instructions will not work correctly if the size
of your program exceeds 64K and the 'table' variable is placed after
the 64K limit. This is because 16-bit addresses span only the 64K
of the segment. The last example above is the most dangerous;
it is likely to crash the system.
Jump tables
Jump tables should be build as tables of 32-bit addresses,
not 16-bit addresses.
Longint (32-bit) Arithmetic
Try to use the longint arithmetic as much as possible.
16-bit instructions often take more space than corresponding
32-bit instructions. In
XOR AX, AX
MOV data1, AX
MOV data2, AX
it would be better to replace the first instruction with
XOR EAX, EAX
which is one byte shorter. Furthermore, if data1 and data2
can be changed into longints, you may save a lot more space (and time)
both in the assembler and the Pascal sections of the program.
ECX vs CX
Loop and repeat instructions in 32-bit mode use the ECX register
rather than CX. The following program segment is likely to cause problems:
MOV CX, size
MOV ESI, source
MOV EDI, dest
REP MOVSB
Also notice that the source and destination registers are ESI and EDI,
rather than SI and DI.
POPAD/PUSHAD
Use POPAD and PUSHAD instead of POPA and PUSHA.
The latter instructions generate only 16-bit pushes.
POPFD/PUSHFD
Use POPFD and PUSHFD instead of POPF and PUSHF.
The latter instructions generate only 16-bit pushes.
IRETD
Use 'IRETD' instead of 'IRET'.
The latter instruction pops 16-bit registers.
String instructions
When doing string operations, it is later to use double word instructions
instead of byte or word. Use MOVSD instead of MOVSW or MOVSB.
JECXZ vs JCXZ
Distinguish between the JCXZ and JECXZ instructions.
The former tests the CX register, while the latter tests ECX.
Use of JCXZ instead of JECXZ may lead to hard-to-find bugs. Similarly,
LOOP tests ECX, while LOOP16 tests CX.
Function results
Remember to return 32-bit results in EAX, not DX:AX.
ES: preservations
Do not change the ES register. TMT Pascal depends on ES = DS.
Immediate PUSH
TMT Pascal assumes that an immediate push instruction like
PUSH Small 0
PUSH Small offset data
Furthermore notice that like TASM and unlike the PharLap assembler,
TMT Pascal will treat
PUSH Word Ptr 0
as if it were
PUSH Word Ptr [0]
Var Parameters
Similar to 16-bit mode, Var parameters are 32-bit pointers.
However, in TMT Pascal, pointers are just 32-bit offsets
within the data segment. Therefore, Var parameters
are retrieved with a 'MOV' instruction, not with an LES or an LDS.
Local Symbols
Local Symbols and Parameters are addressed via the EBP register.
For example, in
var
local: Longint;
asm
MOV EAX, local
end;
the last line assembles into
MOV EAX, [EBP-4]
- 2.3.13. -