Porting low-level DOS code for TP/BP to GO32v2 with FPC

From Lazarus wiki
Revision as of 11:14, 7 April 2013 by Jwdietrich (talk | contribs)
Jump to navigationJump to search

"Low-level DOS code" refers to assembler routines, use of DOS and BIOS functions, etc. This page tries to provide hints regarding general areas of interest when porting such code originally written for TP/BP to GO32v2 target with FPC (or potentially other similar targets like WDOSX). Don't expect any detailed tutorial - messing with low-level code always requires a lot of knowledge and experience, and porting old 16-bit code written for real mode to 32-bit protected mode makes it even more demanding.

  1. Read what our manual, wiki and mailing lists contributions state on FPC calling conventions (i.e. how parameters are passed to functions/procedures and how the stack organization and processing look like) - this is certainly different from TP/BP. Among others, this implies changes of code using [bp].
  2. In general, you should use 32-bit registers rather than 16-bit registers (I believe there's even some speed penalty on some CPUs when using 16-bit registers, but more importantly, the overridden functions (as provided by the DPMI host) may even _require_ providing parameters in 32-bit registers as opposed to e.g. standard DOS functions) - i.e. eax instead of ax, etc.
  3. If you need to exchange data with the underlying 16-bit code like BIOS functions (yes, this includes your read/write sectore functions), the used memory buffer must be placed in a memory area where the 16-bit code can access it (= within the first MB of RAM) if it's your code allocating the buffer and you need to make sure that you can access it too. This is achieved using DPMI functions (read DPMI specification to find out more, or at least have a look at some FPC RTL code using these int 31h functions).
  4. In general, you don't touch any segment registers - all your data are available in flat memory model, where everything is available using 32-bit addressing and ds=es=ss (i.e. no instructions like lds/les needed, no mov es:[xx],yy, etc.). There's one exception directly related to the previous point related to sharing data with 16-bit code - if you pass parameters to/receive results from 16-bit code/functions, you need to translate the 16:16 16-bit addresses to 0:32 addresses used in 32-bit code and vice versa (as described above) and then you obviously might need to change some segment registers too immediately before/after the 16-bit function call (however, these cases are normally solved using helper functions like the DPMI support function for calling 16-bit interrupts, i.e. your code wouldn't be directly messing with segment registers anyway).
  5. Implementation of interrupt service routines or callbacks triggered from real mode requires using special features like locking of memory, etc. - read DPMI specification and potentially have a look at implementation of unit Mouse for GO32v2.