DOS: what changed
Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.
Title: DOS
| Old | New | Line | |
|---|---|---|---|
| 1 | + | > **Note:** This page has outdated information. Somebody is updating the information but you can help. | |
| 2 | + | ||
| 3 | + | ## Overview | |
| 4 | + | ||
| 5 | + | A DOS (8086) cross compiler is currently being developed in FPC trunk (the development version). It started as a hobby project meant to explore how to port FPC to a new platform. | |
| 6 | + | ||
| 7 | + | The number of (FPC on) DOS users is probably quite low, especially since there is an FPC compiler for the more capable [[GO32V2]] DOS extender available which runs on 80386+ processors. | |
| 8 | + | ||
| 9 | + | ### Advantages over FPC for GO32V2 | |
| 10 | + | ||
| 11 | + | - Generated code can run on 16-bit processors. Since these processors are obsolete and out of production, this is mostly useful for [retrocomputing](http://en.wikipedia.org/wiki/Retrocomputing) purposes. Note also that the 80186 is still in use in embedded devices: [1](http://www.cpushack.com/2013/01/12/the-intel-80186-gets-turbocharged-vautomation-turbo186/) | |
| 12 | + | - It's possible to write [TSRs](http://en.wikipedia.org/wiki/Terminate_and_Stay_Resident). | |
| 13 | + | - It's possible to write DOS .SYS device drivers. (Not ready yet, but should be easy to implement) | |
| 14 | + | - It allows writing a bootloader in Pascal. | |
| 15 | + | - It allows writing 16-bit BIOS code in Pascal (e.g. you can now do a project like [SeaBIOS](http://www.seabios.org) but in Pascal). | |
| 16 | + | - It can compile Turbo Pascal 7 code with less changes needed, compared to GO32V2 (no need to port the inline assembly code, for example). | |
| 17 | + | - Real mode DOS programs are less sensitive to bugs in virtual DOS environments, since they're immune to DPMI bugs and in fact require no DPMI at all. (Provided that your program fits within the memory constraints, of course.) | |
| 18 | + | - Compiled binaries are smaller and you don't have to ship CWSDPMI.EXE in order for your program to work under real DOS. | |
| 19 | + | ||
| 20 | + | ### Advantages over Turbo Pascal | |
| 21 | + | ||
| 22 | + | - Compiler is Free/Open Source software and is in active development. | |
| 23 | + | - Supports long file names. | |
| 24 | + | - Not affected (just like FPC for GO32v2) by the infamous CRT unit bug, that causes runtime error 200 on startup when the program is run on a fast CPU. | |
| 25 | + | - Multiple memory models are supported. | |
| 26 | + | - Supports huge pointers. | |
| 27 | + | - Heap manager supports allocating blocks larger than 64 KB (only in the memory models with far data, such as compact, large or huge). | |
| 28 | + | - All the extra Object Pascal features supported by FPC should work. This includes ansistrings, classes, interfaces, exceptions, generics, etc. | |
| 29 | + | - Crosscompilation is doable without running the development system in a dosbox/VM (compile/build on Windows 64-bit, only need 16-bit capable OS for running) | |
| 30 | + | ||
| 31 | + | ### Limitations | |
| 32 | + | ||
| 33 | + | The DOS platforms brings some limitations, like | |
| 34 | + | ||
| 35 | + | - data structures cannot be larger than 64KB | |
| 36 | + | - no simple way of pre-emptive multitasking. | |
| 37 | + | - it is unlikely the Lazarus LCL GUI will be ported to the DOS environment | |
| 38 | + | - However, an [OpenGEM](http://en.wikipedia.org/wiki/OpenGEM) widget set is possible | |
| 39 | + | - Since the large memory model of the i8086 code generator have matured, [[Win16]] support has also been started in FPC trunk | |
| 40 | + | ||
| 41 | + | ## Requirements | |
| 42 | + | ||
| 43 | + | ### FPC 3.0.x | |
| 44 | + | ||
| 45 | + | The compiler is a cross compiler that runs at least on Windows (both x86 and x64), Linux, and macOS. For compiling programs, it needs: | |
| 46 | + | ||
| 47 | + | - the Open Watcom linker - WLINK | |
| 48 | + | - the Open Watcom library manager - WLIB | |
| 49 | + | - the Netwide Assembler - [NASM](http://www.nasm.us/) | |
| 50 | + | ||
| 51 | + | In theory it should be able to run on any platform, supported by FPC, where NASM and the Open Watcom tools are available. This includes DOS via the GO32V2 extender. However, because the Watcom tools for DOS are compiled with a different extender, there are some issues related to long file names and the passing of long command line arguments. This is resolved in FPC trunk, where there's an internal assembler and linker implemented in the compiler itself. | |
| 52 | + | ||
| 53 | + | ### FPC trunk | |
| 54 | + | ||
| 55 | + | FPC trunk contains an internal assembler and linker for DOS, so the Open Watcom tools are no longer required. NASM is still required for building an i8086-msdos snapshot, because of the msdos startup code in the rtl. | |
| 56 | + | ||
| 57 | + | ## Releases | |
| 58 | + | ||
| 59 | + | ### 3.0.4 | |
| 60 | + | ||
| 61 | + | The crosscompiler packages for Windows, Linux - i386 and Linux - x86_64 are also available at the official Free Pascal website: <http://freepascal.org/download.var> | |
| 62 | + | ||
| 63 | + | - Crosscompiler package for Windows: | |
| 64 | + | - <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.4/i386-win32/fpc-3.0.4.i386-win32.cross.i8086-msdos.exe> | |
| 65 | + | - Crosscompiler package for Linux - i386 | |
| 66 | + | - .tar.xz: <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.4/i386-linux/fpc-3.0.4.i386-linux.cross.i8086-msdos.tar.xz> | |
| 67 | + | - RPM: <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.4/i386-linux/fpc-i8086-msdos-3.0.4-1.i686.rpm> | |
| 68 | + | - SRPM: <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.4/i386-linux/fpc-i8086-msdos-3.0.4-1.src.rpm> | |
| 69 | + | - Crosscompiler package for Linux - x86_64 | |
| 70 | + | - .tar.xz: <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.4/x86_64-linux/fpc-3.0.4.x86_64-linux.cross.i8086-msdos.tar.xz> | |
| 71 | + | - RPM: <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.4/x86_64-linux/fpc-i8086-msdos-3.0.4-1.x86_64.rpm> | |
| 72 | + | - SRPM: <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.4/x86_64-linux/fpc-i8086-msdos-3.0.4-1.src.rpm> | |
| 73 | + | ||
| 74 | + | ### 3.0.2 | |
| 75 | + | ||
| 76 | + | - Crosscompiler package for Windows: | |
| 77 | + | - <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.2/i386-win32/fpc-3.0.2.i386-win32.cross.i8086-msdos.exe> | |
| 78 | + | - Crosscompiler package for Linux - i386 | |
| 79 | + | - .tar.xz: <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.2/i386-linux/fpc-3.0.2.i386-linux.cross.i8086-msdos.tar.xz> | |
| 80 | + | - RPM: <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.2/i386-linux/fpc-i8086-msdos-3.0.2-1.i686.rpm> | |
| 81 | + | - SRPM: <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.2/i386-linux/fpc-i8086-msdos-3.0.2-1.src.rpm> | |
| 82 | + | - Crosscompiler package for Linux - x86_64 | |
| 83 | + | - .tar.xz: <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.2/x86_64-linux/fpc-3.0.2.x86_64-linux.cross.i8086-msdos.tar.xz> | |
| 84 | + | - RPM: <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.2/x86_64-linux/fpc-i8086-msdos-3.0.2-1.x86_64.rpm> | |
| 85 | + | - SRPM: <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.2/x86_64-linux/fpc-i8086-msdos-3.0.2-1.src.rpm> | |
| 86 | + | ||
| 87 | + | ### 3.0.0 | |
| 88 | + | ||
| 89 | + | - Crosscompiler package for Windows: | |
| 90 | + | - <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.0/i8086-msdos/fpc-3.0.0.i386-win32.cross.i8086-msdos.exe> | |
| 91 | + | - Crosscompiler package for Linux - i386 | |
| 92 | + | - .tar.xz: <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.0/i386-linux/fpc-3.0.0.i386-linux.cross.i8086-msdos.tar.xz> | |
| 93 | + | - RPM: <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.0/i386-linux/rpm/fpc-i8086-msdos-3.0.0-1.i686.rpm> | |
| 94 | + | - SRPM: <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.0/i386-linux/rpm/fpc-i8086-msdos-3.0.0-1.src.rpm> | |
| 95 | + | - Crosscompiler package for Linux - x86_64 | |
| 96 | + | - .tar.xz: <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.0/x86_64-linux/fpc-3.0.0.x86_64-linux.cross.i8086-msdos.tar.xz> | |
| 97 | + | - RPM: <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.0/x86_64-linux/rpm/fpc-i8086-msdos-3.0.0-1.x86_64.rpm> | |
| 98 | + | - SRPM: <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.0/x86_64-linux/rpm/fpc-i8086-msdos-3.0.0-1.src.rpm> | |
| 99 | + | ||
| 100 | + | ### 3.0.0rc2 | |
| 101 | + | ||
| 102 | + | - Crosscompiler package for Windows: | |
| 103 | + | - <ftp://ftp.freepascal.org/pub/fpc/beta/3.0.0-rc2/i386-win32/fpc-3.0.0rc2.i386-win32.cross.i8086-msdos.exe> | |
| 104 | + | - Crosscompiler package for Linux - i386 | |
| 105 | + | - .tar.xz: <ftp://ftp.freepascal.org/pub/fpc/beta/3.0.0-rc2/i386-linux/fpc-3.0.0rc2.i386-linux.cross.i8086-msdos.tar.xz> | |
| 106 | + | - RPM: <ftp://ftp.freepascal.org/pub/fpc/beta/3.0.0-rc2/i386-linux/rpm/fpc-i8086-msdos-3.0.0-0.rc2.i686.rpm> | |
| 107 | + | - Crosscompiler package for Linux - x86_64 | |
| 108 | + | - .tar.xz: <ftp://ftp.freepascal.org/pub/fpc/beta/3.0.0-rc2/x86_64-linux/fpc-3.0.0rc2.x86_64-linux.cross.i8086-msdos.tar.xz> | |
| 109 | + | - RPM: <ftp://ftp.freepascal.org/pub/fpc/beta/3.0.0-rc2/x86_64-linux/rpm/fpc-i8086-msdos-3.0.0-0.rc2.x86_64.rpm> | |
| 110 | + | ||
| 111 | + | ### 3.0.0rc1 | |
| 112 | + | ||
| 113 | + | - Crosscompiler package for Windows: | |
| 114 | + | - <ftp://ftp.freepascal.org/pub/fpc/beta/3.0.0-rc1/i386-win32/fpc-3.0.0rc1.i8086-msdos.exe> | |
| 115 | + | - Crosscompiler package for Linux - i386 | |
| 116 | + | - .tar.xz: <ftp://ftp.freepascal.org/pub/fpc/beta/3.0.0-rc1/i386-linux/i8086-msdos-fpc-3.0.0rc1.i386-linux.tar.xz> | |
| 117 | + | - RPM: <ftp://ftp.freepascal.org/pub/fpc/beta/3.0.0-rc1/i386-linux/rpm/fpc-i8086-msdos-3.0.0-0.rc1.i686.rpm> | |
| 118 | + | - Crosscompiler package for Linux - x86_64 | |
| 119 | + | - .tar.xz: <ftp://ftp.freepascal.org/pub/fpc/beta/3.0.0-rc1/x86_64-linux/i8086-msdos-fpc-3.0.0rc1.x86_64-linux.tar.xz> | |
| 120 | + | - RPM: <ftp://ftp.freepascal.org/pub/fpc/beta/3.0.0-rc1/x86_64-linux/rpm/fpc-i8086-msdos-3.0.0-0.rc1.x86_64.rpm> | |
| 121 | + | ||
| 122 | + | ## Snapshots | |
| 123 | + | ||
| 124 | + | There are daily snapshots available here: | |
| 125 | + | ||
| 126 | + | <ftp://ftp.freepascal.org/pub/fpc/snapshot/trunk/i8086-msdos/> | |
| 127 | + | ||
| 128 | + | There's also a snapshot available here, but it's quite outdated, so it's better to simply use the above snapshot or to build your own: | |
| 129 | + | ||
| 130 | + | <http://www.bttr-software.de/forum/forum_entry.php?id=12985> | |
| 131 | + | ||
| 132 | + | ### Building a snapshot manually | |
| 133 | + | ||
| 134 | + | - make sure **nasm** is in your path (the fixes-3.0 branch also requires **wlink** and **wlib**) | |
| 135 | + | - checkout fpc trunk: | |
| 136 | + | ||
| 137 | + | `svn checkout `[`http://svn.freepascal.org/svn/fpc/trunk`](http://svn.freepascal.org/svn/fpc/trunk)` fpc` | |
| 138 | + | ||
| 139 | + | - enter the fpc directory and build the compiler with the following command (replace **/usr/bin/ppc386** with the full path to the stable (3.0.4) FPC compiler binary; replace **-WmSmall** with **-WmTiny**, **-WmMedium**, **-WmCompact**, **-WmLarge** or **-WmHuge** if you want to use another memory model): | |
| 140 | + | ||
| 141 | + | `make clean all OS_TARGET=msdos CPU_TARGET=i8086 OPT="-CX -XXs" CROSSOPT=`**`-WmSmall`**` BINUTILSPREFIX= PP=`**`/usr/bin/ppc386`** | |
| 142 | + | ||
| 143 | + | - install the snapshot (replace **linux** and **i386** with the OS and CPU you're using; replace **INSTALL_PREFIX** with the directory you want the snapshot installed): | |
| 144 | + | ||
| 145 | + | `make crossinstall OS_SOURCE=`**`linux`**` CPU_SOURCE=`**`i386`**` OS_TARGET=msdos CPU_TARGET=i8086 PP=compiler/ppcross8086 CROSSOPT=`**`-WmSmall`**` \`\ | |
| 146 | + | ` BINUTILSPREFIX= INSTALL_PREFIX=`**`/home/blablabla/fpc-i8086/snapshot/small`**` OPT="-CX -XXs"` | |
| 147 | + | ||
| 148 | + | ### Updating your fpc.cfg | |
| 149 | + | ||
| 150 | + | Add the following to your fpc.cfg to enable smartlinking and disable the default binutils prefix (so that you don't have to rename nasm, wlink and wlib to msdos-nasm, msdos-wlink and msdos-wlib): | |
| 151 | + | ||
| 152 | + | `#ifdef cpui8086`\ | |
| 153 | + | `-CX`\ | |
| 154 | + | `-XX`\ | |
| 155 | + | `-XP`\ | |
| 156 | + | `#endif` | |
| 157 | + | ||
| 158 | + | To enable building for all the memory models, build snapshots for the tiny, small, medium, compact, large and huge memory model, and then find the lines in your fpc.cfg that specify the path to the RTL: | |
| 159 | + | ||
| 160 | + | `-Fu/usr/lib/fpc/$fpcversion/units/$fpctarget`\ | |
| 161 | + | `-Fu/usr/lib/fpc/$fpcversion/units/$fpctarget/*`\ | |
| 162 | + | `-Fu/usr/lib/fpc/$fpcversion/units/$fpctarget/rtl` | |
| 163 | + | ||
| 164 | + | And update them to something similar to: | |
| 165 | + | ||
| 166 | + | `#IFDEF CPUI8086`\ | |
| 167 | + | `-Fu/home/blablabla/fpc-i8086/snapshot/$fpcmemorymodel/lib/fpc/$fpcversion/units/$fpctarget`\ | |
| 168 | + | `-Fu/home/blablabla/fpc-i8086/snapshot/$fpcmemorymodel/lib/fpc/$fpcversion/units/$fpctarget/*`\ | |
| 169 | + | `-Fu/home/blablabla/fpc-i8086/snapshot/$fpcmemorymodel/lib/fpc/$fpcversion/units/$fpctarget/rtl`\ | |
| 170 | + | `#ELSE`\ | |
| 171 | + | `-Fu/usr/lib/fpc/$fpcversion/units/$fpctarget`\ | |
| 172 | + | `-Fu/usr/lib/fpc/$fpcversion/units/$fpctarget/*`\ | |
| 173 | + | `-Fu/usr/lib/fpc/$fpcversion/units/$fpctarget/rtl`\ | |
| 174 | + | `#ENDIF` | |
| 175 | + | ||
| 176 | + | This should enable you to build programs in any of the supported memory models with just a compiler switch: | |
| 177 | + | ||
| 178 | + | `ppcross8086 -WmTiny -Wtcom hello.pas`\ | |
| 179 | + | `ppcross8086 -WmTiny -Wtexe hello.pas`\ | |
| 180 | + | `ppcross8086 -WmSmall hello.pas`\ | |
| 181 | + | `ppcross8086 -WmMedium hello.pas`\ | |
| 182 | + | `ppcross8086 -WmCompact hello.pas`\ | |
| 183 | + | `ppcross8086 -WmLarge hello.pas`\ | |
| 184 | + | `ppcross8086 -WmHuge hello.pas` | |
| 185 | + | ||
| 186 | + | And in case you're wondering - it doesn't matter which ppcross8086 compiler binary you use (i.e. from the tiny, small, medium, compact, large or huge model snapshot). They are identical. Only the compiled units differ. | |
| 187 | + | ||
| 188 | + | ## Status | |
| 189 | + | ||
| 190 | + | The compiler has been enabled as a CPU/OS target in FPC.exe since revision 25792 (CPU: i8086, OS: msdos). | |
| 191 | + | ||
| 192 | + | The RTL compiles. Most units from Go32v2 have been ported. Just like Go32v2, the RTL supports long file names when run under a Windows 95+/2000+ DOS box or under plain DOS with a long file names driver such as doslfn.exe. FPC demo programs such as fpctris and samegame work in all supported memory models. | |
| 193 | + | ||
| 194 | + | ### Internal linker | |
| 195 | + | ||
| 196 | + | The internal linker does not support all records and features of the OMF object file format. It was designed to support only the records produced by the NASM assembler and FPC's own internal object writer. You may encounter problems if you try to link object modules produced by other compilers and assemblers. | |
| 197 | + | ||
| 198 | + | ### Floating point support | |
| 199 | + | ||
| 200 | + | Floating point operations require an FPU. Software FPU emulation is not yet implemented and using floating point operations on a real machine without an FPU will lead to a hang. | |
| 201 | + | ||
| 202 | + | ### Nil pointer assignment checking | |
| 203 | + | ||
| 204 | + | The **small** and **medium** memory models offer rudimentary nil pointer assignment checking. The system RTL puts a pattern of 32 bytes equal to \$01 at the beginning of the data segment (DS:0000). At the end of program execution, this pattern is checked and if turns out it has changed, the message: | |
| 205 | + | ||
| 206 | + | `Nil pointer assignment` | |
| 207 | + | ||
| 208 | + | is printed on the screen. This indicates that a nil pointer assignment has happened at some time during the program execution. Unfortunately, we can't tell when exactly, only that it has happened. | |
| 209 | + | ||
| 210 | + | ### New pointer types | |
| 211 | + | ||
| 212 | + | To reflect the i8086 segmented memory model, FPC supports several pointer types: | |
| 213 | + | ||
| 214 | + | #### Near pointers | |
| 215 | + | ||
| 216 | + | This is the default pointer type in the tiny, small and medium memory models. | |
| 217 | + | ||
| 218 | + | Near pointers can be declared in any memory model, using the *near* keyword. For example: | |
| 219 | + | ||
| 220 | + | ``` pascal | |
| 221 | + | type | |
| 222 | + | PNearInteger = ^Integer; near; | |
| 223 | + | ``` | |
| 224 | + | ||
| 225 | + | There's also an untyped near pointer, predefined in the system unit, called *NearPointer*. | |
| 226 | + | ||
| 227 | + | #### Special versions of near pointers | |
| 228 | + | ||
| 229 | + | Near pointers are declared using the *near* keyword, followed by a segment register, enclosed in single quotes. For example: | |
| 230 | + | ||
| 231 | + | ``` pascal | |
| 232 | + | type | |
| 233 | + | PNearCSInteger = ^Integer; near 'CS'; | |
| 234 | + | PNearDSInteger = ^Integer; near 'DS'; | |
| 235 | + | PNearESInteger = ^Integer; near 'ES'; | |
| 236 | + | PNearSSInteger = ^Integer; near 'SS'; | |
| 237 | + | PNearFSInteger = ^Integer; near 'FS'; | |
| 238 | + | PNearGSInteger = ^Integer; near 'GS'; | |
| 239 | + | ``` | |
| 240 | + | ||
| 241 | + | There are also untyped versions, predefined in the system unit: | |
| 242 | + | ||
| 243 | + | ` NearCSPointer`\ | |
| 244 | + | ` NearDSPointer`\ | |
| 245 | + | ` NearESPointer`\ | |
| 246 | + | ` NearSSPointer`\ | |
| 247 | + | ` NearFSPointer`\ | |
| 248 | + | ` NearGSPointer` | |
| 249 | + | ||
| 250 | + | #### Far pointers | |
| 251 | + | ||
| 252 | + | This is the default pointer type in the compact, large and huge memory models. | |
| 253 | + | ||
| 254 | + | Far pointers can be declared in any memory model, using the *far* keyword. For example: | |
| 255 | + | ||
| 256 | + | ``` pascal | |
| 257 | + | type | |
| 258 | + | PFarInteger = ^Integer; far; | |
| 259 | + | ``` | |
| 260 | + | ||
| 261 | + | There's also an untyped far pointer, predefined in the system unit, called *FarPointer*. | |
| 262 | + | ||
| 263 | + | #### Huge pointers | |
| 264 | + | ||
| 265 | + | Huge pointers are like far pointers that support pointer arithmetic without the 64kb segment wraparound. That means they will automatically switch to a different segment if the offset exceeds 64k or becomes less than 0. Thus, they are very useful for accessing blocks of memory that exceed 64kb. Additionally, they support normalization, which is explained in the next section. Their main disadvantage is that they are quite a bit slower compared to far pointers. | |
| 266 | + | ||
| 267 | + | Huge pointers are declared using the *huge* keyword. For example: | |
| 268 | + | ||
| 269 | + | ``` pascal | |
| 270 | + | type | |
| 271 | + | PHugeInteger = ^Integer; huge; | |
| 272 | + | ``` | |
| 273 | + | ||
| 274 | + | There's also an untyped huge pointer, predefined in the system unit, called *HugePointer*. | |
| 275 | + | ||
| 276 | + | ##### Huge pointer normalization | |
| 277 | + | ||
| 278 | + | In real mode it is possible for several different pointers to point to the same memory address. For example, the following different pointers point to the same memory location: | |
| 279 | + | ||
| 280 | + | ``` pascal | |
| 281 | + | Ptr($1000, $2345) | |
| 282 | + | Ptr($1200, $0345) | |
| 283 | + | Ptr($1234, $0005) | |
| 284 | + | ``` | |
| 285 | + | ||
| 286 | + | This is because they resolve to the same linear address via the formula (segment * 16 + offset): | |
| 287 | + | ||
| 288 | + | ``` pascal | |
| 289 | + | Ptr($1000, $2345) // -> $1000 * 16 + $2345 = $12345 | |
| 290 | + | Ptr($1200, $0345) // -> $1200 * 16 + $0345 = $12345 | |
| 291 | + | Ptr($1234, $0005) // -> $1234 * 16 + $0005 = $12345 | |
| 292 | + | ``` | |
| 293 | + | ||
| 294 | + | A Pointer whose offset is between \$0 and \$F is called a *normalized* pointer. That's the pointer with the lowest possible offset among all the pointers that point to the same linear address. | |
| 295 | + | ||
| 296 | + | Huge pointers can be automatically normalized by the compiler when doing pointer arithmetic on them or when comparing them. This is controlled by the *\$HugePointerNormalization*, *\$HugePointerArithmeticNormalization* and *\$HugePointerComparisonNormalization* directives. All three of them are local switches, so you can change the modes in the middle of the program. | |
| 297 | + | ||
| 298 | + | ###### \$HugePointerArithmeticNormalization | |
| 299 | + | ||
| 300 | + | This directive controls whether huge pointers are automatically normalized by the compiler after doing pointer arithmetic on them. | |
| 301 | + | ||
| 302 | + | ###### \$HugePointerComparisonNormalization | |
| 303 | + | ||
| 304 | + | This directive controls whether huge pointers are normalized before comparing them. | |
| 305 | + | ||
| 306 | + | ###### \$HugePointerNormalization | |
| 307 | + | ||
| 308 | + | This sets both \$HugePointerArithmeticNormalization and \$HugePointerComparisonNormalization: | |
| 309 | + | ||
| 310 | + | | mode | arithmetic normalization | comparison normalization | description | | |
| 311 | + | |----|----|----|----| | |
| 312 | + | | {\$HugePointerNormalization BorlandC} | On | On | Like Borland C | | |
| 313 | + | | {\$HugePointerNormalization MicrosoftC} | Off | Off | Like Microsoft C | | |
| 314 | + | | {\$HugePointerNormalization WatcomC} | Off | On | Like Watcom C | | |
| 315 | + | ||
| 316 | + | ### Tested machines | |
| 317 | + | ||
| 318 | + | Compiled programs have been tested and known to work on the following machines: | |
| 319 | + | ||
| 320 | + | - [IBM PC 5150](http://oldcomputers.net/ibm5150.html) (the first PC model ever), with a 4.77 MHz 8088 CPU, 512 KB RAM and a CGA card, running IBM DOS 3.30 | |
| 321 | + | - [HP 200LX](http://en.wikipedia.org/wiki/HP_200LX), with a 7.91 MHz 80186 CPU, running MS-DOS 5.0 | |
| 322 | + | - IBM PS/2 Model 30-286, with a 10 MHz 80286 CPU and an AMD 287 FPU, running MS-DOS 6.22 | |
| 323 | + | - various boring 32-bit and 64-bit machines :) | |
| 324 | + | - [DOSBox](http://en.wikipedia.org/wiki/DOSBox) | |
| 325 | + | ||
| 326 | + | ### Supported memory models | |
| 327 | + | ||
| 328 | + | #### Tiny | |
| 329 | + | ||
| 330 | + | - Activated by the `-WmTiny` compiler option | |
| 331 | + | - Code + Data + Heap + Stack \<= 64KB | |
| 332 | + | - CS = DS = SS | |
| 333 | + | - Pointer = NearPointer | |
| 334 | + | - CodePointer = NearPointer | |
| 335 | + | - Code starts at offset \$100 | |
| 336 | + | - Can produce both .com and .exe files. The binary format can be chosen with the `-Wtcom` and `-Wtexe` compiler options. The default format is .exe | |
| 337 | + | - The compiler defines: FPC_MM_TINY | |
| 338 | + | ||
| 339 | + | #### Small | |
| 340 | + | ||
| 341 | + | - Activated by the `-WmSmall` compiler option. This is the default memory model, so it is chosen if you don't specify a memory model. | |
| 342 | + | - Code \<= 64KB, Data + Heap + Stack \<= 64KB (Code and data are in separate segments, so programs can use up to 128KB in total) | |
| 343 | + | - DS = SS | |
| 344 | + | - Pointer = NearPointer | |
| 345 | + | - CodePointer = NearPointer | |
| 346 | + | - Can produce only .exe files | |
| 347 | + | - The compiler defines: FPC_MM_SMALL | |
| 348 | + | ||
| 349 | + | #### Medium | |
| 350 | + | ||
| 351 | + | - Activated by the `-WmMedium` compiler option | |
| 352 | + | - Code \<= 1MB, Data + Heap + Stack \<= 64KB | |
| 353 | + | - DS = SS | |
| 354 | + | - Pointer = NearPointer | |
| 355 | + | - CodePointer = FarPointer | |
| 356 | + | - Can produce only .exe files | |
| 357 | + | - The compiler defines: FPC_MM_MEDIUM | |
| 358 | + | ||
| 359 | + | #### Compact | |
| 360 | + | ||
| 361 | + | - Activated by the `-WmCompact` compiler option | |
| 362 | + | - Code \<= 64KB, Data \<= 64KB, Stack \<= 64KB, Heap \<= 1MB | |
| 363 | + | - Data structures cannot exceed 64KB | |
| 364 | + | - Pointer = FarPointer | |
| 365 | + | - CodePointer = NearPointer | |
| 366 | + | - Can produce only .exe files | |
| 367 | + | - The compiler defines: FPC_MM_COMPACT | |
| 368 | + | ||
| 369 | + | #### Large | |
| 370 | + | ||
| 371 | + | - Activated by the `-WmLarge` compiler option. This is the memory model used by Turbo Pascal version 4 and above | |
| 372 | + | - Code \<= 1MB, Data \<= 64KB, Stack \<= 64KB, Heap \<= 1MB | |
| 373 | + | - Data structures cannot exceed 64KB | |
| 374 | + | - Pointer = FarPointer | |
| 375 | + | - CodePointer = FarPointer | |
| 376 | + | - Can produce only .exe files | |
| 377 | + | - The compiler defines: FPC_MM_LARGE | |
| 378 | + | ||
| 379 | + | #### Huge | |
| 380 | + | ||
| 381 | + | - Activated by the `-WmHuge` compiler option | |
| 382 | + | - Code \<= 1MB, Data \<= 1MB, Stack \<= 64KB, Heap \<= 1MB | |
| 383 | + | - Static data of a single pascal module (i.e. unit or program) cannot exceed 64KB | |
| 384 | + | - Data structures cannot exceed 64KB | |
| 385 | + | - Pointer = FarPointer | |
| 386 | + | - CodePointer = FarPointer | |
| 387 | + | - Can produce only .exe files | |
| 388 | + | - The compiler defines: FPC_MM_HUGE | |
| 389 | + | ||
| 390 | + | ### Units and programs exceeding 64KB of code | |
| 391 | + | ||
| 392 | + | Although the medium, large and huge memory models support up to 1MB of code for the whole program+units, there's still a limit of 64kb code per pascal module (i.e. unit or program). If this limit is exceeded, you can overcome this by splitting the unit or program that exceeded 64KB into smaller units, so that each of them stays within the 64KB limit. But there's also an easier solution. You can put the following directive in the module that exceeds 64KB: | |
| 393 | + | ||
| 394 | + | `{$HUGECODE on}` | |
| 395 | + | ||
| 396 | + | This forces each procedure and function to be in a separate segment. Note that since the code of the unit is no longer in a single segment, this also disallows mixing near and far procedures in the same unit, so in this mode, 'near' and {\$F-} are ignored. | |
| 397 | + | ||
| 398 | + | Using {\$HUGECODE on} does not count as using a different memory model, because you can freely mix units with {\$HUGECODE on} and {\$HUGECODE off} in the same program. | |
| 399 | + | ||
| 400 | + | ### Supported calling conventions | |
| 401 | + | ||
| 402 | + | Currently, only the Pascal calling convention is supported. All the other calling conventions are entirely untested and should not be used, because they may or may not work and may change at any time. | |
| 403 | + | ||
| 404 | + | #### Pascal | |
| 405 | + | ||
| 406 | + | This is the default calling convention. It strives for compatibility with Turbo Pascal 7. | |
| 407 | + | ||
| 408 | + | - Parameters are pushed on the stack left to right. | |
| 409 | + | - The callee cleans the parameters from the stack. | |
| 410 | + | - Procedures and functions must preserve DS, SS and BP and may destroy AX, BX, CX, DX, SI, DI and ES. | |
| 411 | + | - 16-bit results are returned in AX, 32-bit results in DX:AX | |
| 412 | + | - 64-bit ints are returned in AX:BX:CX:DX. Note that Turbo Pascal doesn't support int64, so this behavior is borrowed from Open Watcom's 'pascal' calling convention. | |
| 413 | + | ||
| 414 | + | ## Troubleshooting | |
| 415 | + | ||
| 416 | + | ### Compile error: missing .o files | |
| 417 | + | ||
| 418 | + | Problem: If you see errors/warnings like this during compiling & linking: | |
| 419 | + | ||
| 420 | + | ```text | |
| 421 | + | test.pas(12,24) Warning: Object system.o not found, Linking may fail ! | |
| 422 | + | Error! E2008: cannot open system.o : No such file or directory | |
| 423 | + | ``` | |
| 424 | + | ||
| 425 | + | (and indeed there don't appear to be any .o files in your msdos units directory) | |
| 426 | + | ||
| 427 | + | Solution: You haven't used smartlinking. You should always compile i8086-msdos programs with smartlinking, i.e. use the -XX and -CX options. Smartlinking uses .a files, nonsmartlinking uses .o files. | |
| 428 | + | ||
| 429 | + | The reason the .o files aren't generated is because the system unit exceeds the 64kb code limit for the small and tiny memory models and is therefore impossible to compile even 'hello world' without smartlinking, so creating the .o files is a waste of time. It might work for the medium model, but then you have to build the snapshot without -CX. However, with the tight memory constraints of real mode DOS, there is little reason not to use smartlinking in every memory model. Also, the medium model still has a limit of 64k code per unit, so even there it might not work without smartlinking. It certainly hasn't been tested. | |
| 430 | + | ||
| 431 | + | Hint: You can add these options to your fpc.cfg file, as described in the "Updating your fpc.cfg" section. | |
| 432 | + | ||
| 433 | + | ## Running the testsuite | |
| 434 | + | ||
| 435 | + | ### Using DOSBox | |
| 436 | + | ||
| 437 | + | - build a snapshot for the memory model you want to test | |
| 438 | + | - it is recomended to use a 32-bit x86 build of DOSBox, because the 64-bit one has inaccurate FPU emulation | |
| 439 | + | - compile fpc/tests/utils/dosbox/dosbox_wrapper.pas for your native platform | |
| 440 | + | - prepare and run a script like this: | |
| 441 | + | ||
| 442 | + | ``` bash | |
| 443 | + | #!/bin/sh | |
| 444 | + | ||
| 445 | + | FPCDIR=/home/blablabla/fpc-i8086/fpc | |
| 446 | + | MEMMODEL=Small | |
| 447 | + | ||
| 448 | + | export FPCMAKE=$FPCDIR/utils/fpcm/fpcmake | |
| 449 | + | export DOSBOX=/usr/bin/dosbox | |
| 450 | + | export SDL_VIDEODRIVER=dummy | |
| 451 | + | export SDL_AUDIODRIVER=dummy | |
| 452 | + | ||
| 453 | + | cd $FPCDIR/tests/ | |
| 454 | + | ||
| 455 | + | ulimit -m 256000 | |
| 456 | + | #ulimit -v 256000 | |
| 457 | + | ulimit -d 256000 | |
| 458 | + | ||
| 459 | + | echo running testsuite | |
| 460 | + | make full FPCFPMAKE=$FPCDIR/compiler/ppcx64 TEST_FPC=$FPCDIR/compiler/ppcross8086 TEST_OPT=-Wm$MEMMODEL EMULATOR=$FPCDIR/tests/utils/dosbox/dosbox_wrapper | |
| 461 | + | ``` | |
| 462 | + | ||
| 463 | + | ## See also | |
| 464 | + | ||
| 465 | + | - [[GO32V2]] - DOS Extender | |
| 466 | + | - [[go32v2 development]] | |
| 467 | + | ||
| 468 | + | --- | |
| 469 | + | *From the Free Pascal wiki, page "DOS", as it stood on 2021-04-14 after a change by Ñuño Martínez, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).* | |
| 470 | + | Category: Cross compilation | |
| 471 | + | Category: DOS | |
| 472 | + | Category: FPC | |
| 473 | + | Category: FPC internals | |
| 474 | + | Category: Historical | |
| 475 | + | Category: Operating Systems and Platforms |
