Sign in Join
Wiki copytemporary

DOS: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11> **Note:** This page has outdated information. Somebody is updating the information but you can help.
22
33## Overview
44
55A 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.
66
77The 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.
88
99### Advantages over FPC for GO32V2
1010
1111- 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/)
1212- It's possible to write [TSRs](http://en.wikipedia.org/wiki/Terminate_and_Stay_Resident).
1313- It's possible to write DOS .SYS device drivers. (Not ready yet, but should be easy to implement)
1414- It allows writing a bootloader in Pascal.
1515- 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).
1616- It can compile Turbo Pascal 7 code with less changes needed, compared to GO32V2 (no need to port the inline assembly code, for example).
1717- 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.)
1818- Compiled binaries are smaller and you don't have to ship CWSDPMI.EXE in order for your program to work under real DOS.
1919
2020### Advantages over Turbo Pascal
2121
2222- Compiler is Free/Open Source software and is in active development.
2323- Supports long file names.
2424- 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.
2525- Multiple memory models are supported.
2626- Supports huge pointers.
2727- Heap manager supports allocating blocks larger than 64 KB (only in the memory models with far data, such as compact, large or huge).
2828- All the extra Object Pascal features supported by FPC should work. This includes ansistrings, classes, interfaces, exceptions, generics, etc.
2929- 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)
3030
3131### Limitations
3232
3333The DOS platforms brings some limitations, like
3434
3535- data structures cannot be larger than 64KB
3636- no simple way of pre-emptive multitasking.
3737- it is unlikely the Lazarus LCL GUI will be ported to the DOS environment
3838 - However, an [OpenGEM](http://en.wikipedia.org/wiki/OpenGEM) widget set is possible
3939 - Since the large memory model of the i8086 code generator have matured, [[Win16]] support has also been started in FPC trunk
4040
4141## Requirements
4242
4343### FPC 3.0.x
4444
4545The compiler is a cross compiler that runs at least on Windows (both x86 and x64), Linux, and macOS. For compiling programs, it needs:
4646
4747- the Open Watcom linker - WLINK
4848- the Open Watcom library manager - WLIB
4949- the Netwide Assembler - [NASM](http://www.nasm.us/)
5050
5151In 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.
5252
5353### FPC trunk
5454
5555FPC 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.
5656
5757## Releases
5858
5959### 3.0.4
6060
6161The crosscompiler packages for Windows, Linux - i386 and Linux - x86_64 are also available at the official Free Pascal website: <http://freepascal.org/download.var>
6262
6363- Crosscompiler package for Windows:
6464 - <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.4/i386-win32/fpc-3.0.4.i386-win32.cross.i8086-msdos.exe>
6565- Crosscompiler package for Linux - i386
6666 - .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>
6767 - RPM: <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.4/i386-linux/fpc-i8086-msdos-3.0.4-1.i686.rpm>
6868 - SRPM: <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.4/i386-linux/fpc-i8086-msdos-3.0.4-1.src.rpm>
6969- Crosscompiler package for Linux - x86_64
7070 - .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>
7171 - RPM: <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.4/x86_64-linux/fpc-i8086-msdos-3.0.4-1.x86_64.rpm>
7272 - SRPM: <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.4/x86_64-linux/fpc-i8086-msdos-3.0.4-1.src.rpm>
7373
7474### 3.0.2
7575
7676- Crosscompiler package for Windows:
7777 - <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.2/i386-win32/fpc-3.0.2.i386-win32.cross.i8086-msdos.exe>
7878- Crosscompiler package for Linux - i386
7979 - .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>
8080 - RPM: <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.2/i386-linux/fpc-i8086-msdos-3.0.2-1.i686.rpm>
8181 - SRPM: <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.2/i386-linux/fpc-i8086-msdos-3.0.2-1.src.rpm>
8282- Crosscompiler package for Linux - x86_64
8383 - .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>
8484 - RPM: <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.2/x86_64-linux/fpc-i8086-msdos-3.0.2-1.x86_64.rpm>
8585 - SRPM: <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.2/x86_64-linux/fpc-i8086-msdos-3.0.2-1.src.rpm>
8686
8787### 3.0.0
8888
8989- Crosscompiler package for Windows:
9090 - <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.0/i8086-msdos/fpc-3.0.0.i386-win32.cross.i8086-msdos.exe>
9191- Crosscompiler package for Linux - i386
9292 - .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>
9393 - RPM: <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.0/i386-linux/rpm/fpc-i8086-msdos-3.0.0-1.i686.rpm>
9494 - SRPM: <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.0/i386-linux/rpm/fpc-i8086-msdos-3.0.0-1.src.rpm>
9595- Crosscompiler package for Linux - x86_64
9696 - .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>
9797 - 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>
9898 - SRPM: <ftp://ftp.freepascal.org/pub/fpc/dist/3.0.0/x86_64-linux/rpm/fpc-i8086-msdos-3.0.0-1.src.rpm>
9999
100100### 3.0.0rc2
101101
102102- Crosscompiler package for Windows:
103103 - <ftp://ftp.freepascal.org/pub/fpc/beta/3.0.0-rc2/i386-win32/fpc-3.0.0rc2.i386-win32.cross.i8086-msdos.exe>
104104- Crosscompiler package for Linux - i386
105105 - .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>
106106 - 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>
107107- Crosscompiler package for Linux - x86_64
108108 - .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>
109109 - 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>
110110
111111### 3.0.0rc1
112112
113113- Crosscompiler package for Windows:
114114 - <ftp://ftp.freepascal.org/pub/fpc/beta/3.0.0-rc1/i386-win32/fpc-3.0.0rc1.i8086-msdos.exe>
115115- Crosscompiler package for Linux - i386
116116 - .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>
117117 - 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>
118118- Crosscompiler package for Linux - x86_64
119119 - .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>
120120 - 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>
121121
122122## Snapshots
123123
124124There are daily snapshots available here:
125125
126126<ftp://ftp.freepascal.org/pub/fpc/snapshot/trunk/i8086-msdos/>
127127
128128There'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:
129129
130130<http://www.bttr-software.de/forum/forum_entry.php?id=12985>
131131
132132### Building a snapshot manually
133133
134134- make sure **nasm** is in your path (the fixes-3.0 branch also requires **wlink** and **wlib**)
135135- checkout fpc trunk:
136136
137-`svn checkout `[`http://svn.freepascal.org/svn/fpc/trunk`](http://svn.freepascal.org/svn/fpc/trunk)` fpc`
137+```text
138+svn checkout http://svn.freepascal.org/svn/fpc/trunk fpc
139+```
138140
139141- 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):
140142
141-`make clean all OS_TARGET=msdos CPU_TARGET=i8086 OPT="-CX -XXs" CROSSOPT=`**`-WmSmall`**` BINUTILSPREFIX= PP=`**`/usr/bin/ppc386`**
143+```text
144+make clean all OS_TARGET=msdos CPU_TARGET=i8086 OPT="-CX -XXs" CROSSOPT=-WmSmall BINUTILSPREFIX= PP=/usr/bin/ppc386
145+```
142146
143147- 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):
144148
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"`
149+```text
150+make crossinstall OS_SOURCE=linux CPU_SOURCE=i386 OS_TARGET=msdos CPU_TARGET=i8086 PP=compiler/ppcross8086 CROSSOPT=-WmSmall \
151+ BINUTILSPREFIX= INSTALL_PREFIX=/home/blablabla/fpc-i8086/snapshot/small OPT="-CX -XXs"
152+```
147153
148154### Updating your fpc.cfg
149155
150156Add 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):
151157
152-`#ifdef cpui8086`\
153-`-CX`\
154-`-XX`\
155-`-XP`\
156-`#endif`
158+```text
159+#ifdef cpui8086
160+-CX
161+-XX
162+-XP
163+#endif
164+```
157165
158166To 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:
159167
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`
168+```text
169+-Fu/usr/lib/fpc/$fpcversion/units/$fpctarget
170+-Fu/usr/lib/fpc/$fpcversion/units/$fpctarget/*
171+-Fu/usr/lib/fpc/$fpcversion/units/$fpctarget/rtl
172+```
163173
164174And update them to something similar to:
165175
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`
176+```text
177+#IFDEF CPUI8086
178+-Fu/home/blablabla/fpc-i8086/snapshot/$fpcmemorymodel/lib/fpc/$fpcversion/units/$fpctarget
179+-Fu/home/blablabla/fpc-i8086/snapshot/$fpcmemorymodel/lib/fpc/$fpcversion/units/$fpctarget/*
180+-Fu/home/blablabla/fpc-i8086/snapshot/$fpcmemorymodel/lib/fpc/$fpcversion/units/$fpctarget/rtl
181+#ELSE
182+-Fu/usr/lib/fpc/$fpcversion/units/$fpctarget
183+-Fu/usr/lib/fpc/$fpcversion/units/$fpctarget/*
184+-Fu/usr/lib/fpc/$fpcversion/units/$fpctarget/rtl
185+#ENDIF
186+```
175187
176188This should enable you to build programs in any of the supported memory models with just a compiler switch:
177189
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`
190+```text
191+ppcross8086 -WmTiny -Wtcom hello.pas
192+ppcross8086 -WmTiny -Wtexe hello.pas
193+ppcross8086 -WmSmall hello.pas
194+ppcross8086 -WmMedium hello.pas
195+ppcross8086 -WmCompact hello.pas
196+ppcross8086 -WmLarge hello.pas
197+ppcross8086 -WmHuge hello.pas
198+```
185199
186200And 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.
187201
188202## Status
189203
190204The compiler has been enabled as a CPU/OS target in FPC.exe since revision 25792 (CPU: i8086, OS: msdos).
191205
192206The 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.
193207
194208### Internal linker
195209
196210The 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.
197211
198212### Floating point support
199213
200214Floating 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.
201215
202216### Nil pointer assignment checking
203217
204218The **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:
205219
206-`Nil pointer assignment`
220+```text
221+Nil pointer assignment
222+```
207223
208224is 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.
209225
210226### New pointer types
211227
212228To reflect the i8086 segmented memory model, FPC supports several pointer types:
213229
214230#### Near pointers
215231
216232This is the default pointer type in the tiny, small and medium memory models.
217233
218234Near pointers can be declared in any memory model, using the *near* keyword. For example:
219235
220236``` pascal
221237type
222238 PNearInteger = ^Integer; near;
223239```
224240
225241There's also an untyped near pointer, predefined in the system unit, called *NearPointer*.
226242
227243#### Special versions of near pointers
228244
229245Near pointers are declared using the *near* keyword, followed by a segment register, enclosed in single quotes. For example:
230246
231247``` pascal
232248type
233249 PNearCSInteger = ^Integer; near 'CS';
234250 PNearDSInteger = ^Integer; near 'DS';
235251 PNearESInteger = ^Integer; near 'ES';
236252 PNearSSInteger = ^Integer; near 'SS';
237253 PNearFSInteger = ^Integer; near 'FS';
238254 PNearGSInteger = ^Integer; near 'GS';
239255```
240256
241257There are also untyped versions, predefined in the system unit:
242258
243-` NearCSPointer`\
244-` NearDSPointer`\
245-` NearESPointer`\
246-` NearSSPointer`\
247-` NearFSPointer`\
248-` NearGSPointer`
259+```text
260+ NearCSPointer
261+ NearDSPointer
262+ NearESPointer
263+ NearSSPointer
264+ NearFSPointer
265+ NearGSPointer
266+```
249267
250268#### Far pointers
251269
252270This is the default pointer type in the compact, large and huge memory models.
253271
254272Far pointers can be declared in any memory model, using the *far* keyword. For example:
255273
256274``` pascal
257275type
258276 PFarInteger = ^Integer; far;
259277```
260278
261279There's also an untyped far pointer, predefined in the system unit, called *FarPointer*.
262280
263281#### Huge pointers
264282
265283Huge 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.
266284
267285Huge pointers are declared using the *huge* keyword. For example:
268286
269287``` pascal
270288type
271289 PHugeInteger = ^Integer; huge;
272290```
273291
274292There's also an untyped huge pointer, predefined in the system unit, called *HugePointer*.
275293
276294##### Huge pointer normalization
277295
278296In 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:
279297
280298``` pascal
281299Ptr($1000, $2345)
282300Ptr($1200, $0345)
283301Ptr($1234, $0005)
284302```
285303
286304This is because they resolve to the same linear address via the formula (segment * 16 + offset):
287305
288306``` pascal
289307Ptr($1000, $2345) // -> $1000 * 16 + $2345 = $12345
290308Ptr($1200, $0345) // -> $1200 * 16 + $0345 = $12345
291309Ptr($1234, $0005) // -> $1234 * 16 + $0005 = $12345
292310```
293311
294312A 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.
295313
296314Huge 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.
297315
298316###### \$HugePointerArithmeticNormalization
299317
300318This directive controls whether huge pointers are automatically normalized by the compiler after doing pointer arithmetic on them.
301319
302320###### \$HugePointerComparisonNormalization
303321
304322This directive controls whether huge pointers are normalized before comparing them.
305323
306324###### \$HugePointerNormalization
307325
308326This sets both \$HugePointerArithmeticNormalization and \$HugePointerComparisonNormalization:
309327
310328| mode | arithmetic normalization | comparison normalization | description |
311329|----|----|----|----|
312330| {\$HugePointerNormalization BorlandC} | On | On | Like Borland C |
313331| {\$HugePointerNormalization MicrosoftC} | Off | Off | Like Microsoft C |
314332| {\$HugePointerNormalization WatcomC} | Off | On | Like Watcom C |
315333
316334### Tested machines
317335
318336Compiled programs have been tested and known to work on the following machines:
319337
320338- [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
321339- [HP 200LX](http://en.wikipedia.org/wiki/HP_200LX), with a 7.91 MHz 80186 CPU, running MS-DOS 5.0
322340- IBM PS/2 Model 30-286, with a 10 MHz 80286 CPU and an AMD 287 FPU, running MS-DOS 6.22
323341- various boring 32-bit and 64-bit machines :)
324342- [DOSBox](http://en.wikipedia.org/wiki/DOSBox)
325343
326344### Supported memory models
327345
328346#### Tiny
329347
330348- Activated by the `-WmTiny` compiler option
331349- Code + Data + Heap + Stack \<= 64KB
332350- CS = DS = SS
333351- Pointer = NearPointer
334352- CodePointer = NearPointer
335353- Code starts at offset \$100
336354- 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
337355- The compiler defines: FPC_MM_TINY
338356
339357#### Small
340358
341359- Activated by the `-WmSmall` compiler option. This is the default memory model, so it is chosen if you don't specify a memory model.
342360- Code \<= 64KB, Data + Heap + Stack \<= 64KB (Code and data are in separate segments, so programs can use up to 128KB in total)
343361- DS = SS
344362- Pointer = NearPointer
345363- CodePointer = NearPointer
346364- Can produce only .exe files
347365- The compiler defines: FPC_MM_SMALL
348366
349367#### Medium
350368
351369- Activated by the `-WmMedium` compiler option
352370- Code \<= 1MB, Data + Heap + Stack \<= 64KB
353371- DS = SS
354372- Pointer = NearPointer
355373- CodePointer = FarPointer
356374- Can produce only .exe files
357375- The compiler defines: FPC_MM_MEDIUM
358376
359377#### Compact
360378
361379- Activated by the `-WmCompact` compiler option
362380- Code \<= 64KB, Data \<= 64KB, Stack \<= 64KB, Heap \<= 1MB
363381- Data structures cannot exceed 64KB
364382- Pointer = FarPointer
365383- CodePointer = NearPointer
366384- Can produce only .exe files
367385- The compiler defines: FPC_MM_COMPACT
368386
369387#### Large
370388
371389- Activated by the `-WmLarge` compiler option. This is the memory model used by Turbo Pascal version 4 and above
372390- Code \<= 1MB, Data \<= 64KB, Stack \<= 64KB, Heap \<= 1MB
373391- Data structures cannot exceed 64KB
374392- Pointer = FarPointer
375393- CodePointer = FarPointer
376394- Can produce only .exe files
377395- The compiler defines: FPC_MM_LARGE
378396
379397#### Huge
380398
381399- Activated by the `-WmHuge` compiler option
382400- Code \<= 1MB, Data \<= 1MB, Stack \<= 64KB, Heap \<= 1MB
383401- Static data of a single pascal module (i.e. unit or program) cannot exceed 64KB
384402- Data structures cannot exceed 64KB
385403- Pointer = FarPointer
386404- CodePointer = FarPointer
387405- Can produce only .exe files
388406- The compiler defines: FPC_MM_HUGE
389407
390408### Units and programs exceeding 64KB of code
391409
392410Although 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:
393411
394-`{$HUGECODE on}`
412+```text
413+{$HUGECODE on}
414+```
395415
396416This 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.
397417
398418Using {\$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.
399419
400420### Supported calling conventions
401421
402422Currently, 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.
403423
404424#### Pascal
405425
406426This is the default calling convention. It strives for compatibility with Turbo Pascal 7.
407427
408428- Parameters are pushed on the stack left to right.
409429- The callee cleans the parameters from the stack.
410430- Procedures and functions must preserve DS, SS and BP and may destroy AX, BX, CX, DX, SI, DI and ES.
411431- 16-bit results are returned in AX, 32-bit results in DX:AX
412432- 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.
413433
414434## Troubleshooting
415435
416436### Compile error: missing .o files
417437
418438Problem: If you see errors/warnings like this during compiling & linking:
419439
420440```text
421441test.pas(12,24) Warning: Object system.o not found, Linking may fail !
422442Error! E2008: cannot open system.o : No such file or directory
423443```
424444
425445(and indeed there don't appear to be any .o files in your msdos units directory)
426446
427447Solution: 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.
428448
429449The 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.
430450
431451Hint: You can add these options to your fpc.cfg file, as described in the "Updating your fpc.cfg" section.
432452
433453## Running the testsuite
434454
435455### Using DOSBox
436456
437457- build a snapshot for the memory model you want to test
438458- it is recomended to use a 32-bit x86 build of DOSBox, because the 64-bit one has inaccurate FPU emulation
439459- compile fpc/tests/utils/dosbox/dosbox_wrapper.pas for your native platform
440460- prepare and run a script like this:
441461
442462``` bash
443463#!/bin/sh
444464
445465FPCDIR=/home/blablabla/fpc-i8086/fpc
446466MEMMODEL=Small
447467
448468export FPCMAKE=$FPCDIR/utils/fpcm/fpcmake
449469export DOSBOX=/usr/bin/dosbox
450470export SDL_VIDEODRIVER=dummy
451471export SDL_AUDIODRIVER=dummy
452472
453473cd $FPCDIR/tests/
454474
455475ulimit -m 256000
456476#ulimit -v 256000
457477ulimit -d 256000
458478
459479echo running testsuite
460480make full FPCFPMAKE=$FPCDIR/compiler/ppcx64 TEST_FPC=$FPCDIR/compiler/ppcross8086 TEST_OPT=-Wm$MEMMODEL EMULATOR=$FPCDIR/tests/utils/dosbox/dosbox_wrapper
461481```
462482
463483## See also
464484
465485- [[GO32V2]] - DOS Extender
466486- [[go32v2 development]]
467487
468488---
469489*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).*
470490Category: Cross compilation
471491Category: DOS
472492Category: FPC
473493Category: FPC internals
474494Category: Historical
475495Category: Operating Systems and Platforms

Back to history