Using 386/486 32-bit instructions in Turbo Pascal's BASM

The "built-in assembler" [BASM] is undoubtedly TP6's most appealing feature. The fact that it understands Pascal declarations makes it much easier (and safer) to use than external procedures, which had to live in a separate .ASM file and required redeclaration of argument and global variable types. As if this isn't significant enough, the way BASM blocks can be freely embedded in Pascal code has rendered the illegible and under-powered Inline escape nearly obsolete. (We're still stuck with Inline for use in macros, and can only hope that TP7 will support Real Macros, that can be written in Pascal or in BASM.)

The only fly in the BASM ointment (besides the no-macro one) is that it doesn't support the 386/486 32-bit instructions. Obviously, in real mode we don't have much use for flat 32-bit addressing, but expressions that require multiplying and dividing LongInts can be dramatically faster when they use the hardware's 32-bit operations than when they call the RTL's 32-bit subroutines. Similarly, just as REP MOVSW is twice as fast as an equivalent REP MOVSB (assuming the data is word aligned), REP MOVSD is twice as fast as REP MOVSW (for dword aligned data). (The performance is quite a bit less impressive with misaligned data, but the "wider" moves are still faster than the "narrower" ones.)

Fortunately, at least this time, "not supported" is not the same as "can't do". Just like TASM, BASM allows you to freely mix data in with your code. While a Pascal var statement between two procedures will (at least potentially) allocate space in an entirely different segment, a db declaration between two assembler statements will be placed right between the assembled opcodes. Since the 386/486 (in real mode) uses an instruction prefix byte to convert 16-bit ops like MOVSW to 32-bit ones like MOVSD, "all" we have to do to use the 386/486 32-bit operations from BASM is to put the appropriate prefix byte before normal 16-bit instructions.

One potential complication is that there are two different "32-bit" prefixes:

const
  D32 = $66; {32-bit data}
  A32 = $67; {32-bit addresses}
However, since most uses for 32-bit operations under DOS involve 32-bit math or dword-at-a-time string operations, you will almost always use D32. Where in TASM you would simply say "imul ebx" to do a signed multiply of EAX and EBX with the 64-bit result in EDX:EAX, in BASM you would have to say "db D32; imul bx". Similarly, TASM's "REP MOVSD" and "REP STOSD" become BASM's "db D32; REP MOVSW" and "db D32; REP STOSW".

Obviously, this isn't as easy or as safe as just referring to EAX, say, but it's sure better than not being able to use the 32-bit instructions at all!


This article originally appeared in PC Techniques.

Copyright © 1991, Jon Shemitz - jon@midnightbeach.com - html markup 8-26-94

KBD icon Return to Publications list