From a45f1cdd3333afb7f97238e56e550a3f1100004c Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 3 Aug 2022 20:32:58 +0200 Subject: [PATCH 01/20] Allow stosw, lodsw, scasw. --- mach/i386/as/mach3.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mach/i386/as/mach3.c b/mach/i386/as/mach3.c index 37f03566b..d5156ae0c 100644 --- a/mach/i386/as/mach3.c +++ b/mach/i386/as/mach3.c @@ -184,10 +184,13 @@ {0, NOOP_1, 0155, "ins"}, {0, NOOP_1, 0252, "stosb"}, {0, NOOP_1, 0253, "stos"}, +{0, NOOP_1, 0253, "stosw"}, {0, NOOP_1, 0254, "lodsb"}, {0, NOOP_1, 0255, "lods"}, +{0, NOOP_1, 0255, "lodsw"}, {0, NOOP_1, 0256, "scasb"}, {0, NOOP_1, 0257, "scas"}, +{0, NOOP_1, 0257, "scasw"}, {0, NOOP_1, 0311, "leave"}, {0, NOOP_1, 0316, "into"}, {0, NOOP_1, 0317, "iret"}, From 6d9ac0b182fad0946f46031ce354ee322a6ad60b Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 3 Aug 2022 20:41:06 +0200 Subject: [PATCH 02/20] Add the nonfunctional boilerplate for the MSDOS 386 port. --- build.lua | 1 + plat/msdos/include/ack/plat.h | 11 ++ plat/msdos/include/build.lua | 24 +++ plat/msdos/include/sys/types.h | 9 + plat/{msdos86 => msdos}/libsys/brk.c | 0 plat/msdos/libsys/build.lua | 28 +++ plat/{msdos86 => msdos}/libsys/creat.c | 0 plat/{msdos86 => msdos}/libsys/gettimeofday.c | 0 plat/{msdos86 => msdos}/libsys/kill.c | 0 plat/{msdos86 => msdos}/libsys/libsys.h | 0 plat/{msdos86 => msdos}/libsys/lseek.c | 0 plat/{msdos86 => msdos}/libsys/open.c | 0 plat/{msdos86 => msdos}/libsys/read.c | 0 plat/{msdos86 => msdos}/libsys/setmode.c | 0 plat/{msdos86 => msdos}/libsys/signal.c | 0 plat/{msdos86 => msdos}/libsys/sys_fdmodes.c | 0 plat/{msdos86 => msdos}/libsys/sys_getmode.c | 0 plat/{msdos86 => msdos}/libsys/sys_initmain.c | 0 plat/{msdos86 => msdos}/libsys/sys_iseof.c | 0 plat/{msdos86 => msdos}/libsys/sys_seteof.c | 0 plat/{msdos86 => msdos}/libsys/sys_seterrno.c | 0 plat/{msdos86 => msdos}/libsys/sys_setmode.c | 0 plat/{msdos86 => msdos}/libsys/write.c | 0 plat/msdos386/boot.s | 170 ++++++++++++++++++ plat/msdos386/build-pkg.lua | 25 +++ plat/msdos386/build-tools.lua | 21 +++ plat/msdos386/descr | 77 ++++++++ plat/msdos386/include/ack/plat.h | 6 + plat/msdos386/include/build.lua | 24 +++ plat/msdos386/include/sys/types.h | 9 + plat/msdos386/libsys/build.lua | 47 +++++ plat/msdos86/libsys/build.lua | 19 +- 32 files changed, 454 insertions(+), 17 deletions(-) create mode 100644 plat/msdos/include/ack/plat.h create mode 100644 plat/msdos/include/build.lua create mode 100644 plat/msdos/include/sys/types.h rename plat/{msdos86 => msdos}/libsys/brk.c (100%) create mode 100644 plat/msdos/libsys/build.lua rename plat/{msdos86 => msdos}/libsys/creat.c (100%) rename plat/{msdos86 => msdos}/libsys/gettimeofday.c (100%) rename plat/{msdos86 => msdos}/libsys/kill.c (100%) rename plat/{msdos86 => msdos}/libsys/libsys.h (100%) rename plat/{msdos86 => msdos}/libsys/lseek.c (100%) rename plat/{msdos86 => msdos}/libsys/open.c (100%) rename plat/{msdos86 => msdos}/libsys/read.c (100%) rename plat/{msdos86 => msdos}/libsys/setmode.c (100%) rename plat/{msdos86 => msdos}/libsys/signal.c (100%) rename plat/{msdos86 => msdos}/libsys/sys_fdmodes.c (100%) rename plat/{msdos86 => msdos}/libsys/sys_getmode.c (100%) rename plat/{msdos86 => msdos}/libsys/sys_initmain.c (100%) rename plat/{msdos86 => msdos}/libsys/sys_iseof.c (100%) rename plat/{msdos86 => msdos}/libsys/sys_seteof.c (100%) rename plat/{msdos86 => msdos}/libsys/sys_seterrno.c (100%) rename plat/{msdos86 => msdos}/libsys/sys_setmode.c (100%) rename plat/{msdos86 => msdos}/libsys/write.c (100%) create mode 100644 plat/msdos386/boot.s create mode 100644 plat/msdos386/build-pkg.lua create mode 100644 plat/msdos386/build-tools.lua create mode 100644 plat/msdos386/descr create mode 100644 plat/msdos386/include/ack/plat.h create mode 100644 plat/msdos386/include/build.lua create mode 100644 plat/msdos386/include/sys/types.h create mode 100644 plat/msdos386/libsys/build.lua diff --git a/build.lua b/build.lua index 319571d8a..b0c2beebd 100644 --- a/build.lua +++ b/build.lua @@ -12,6 +12,7 @@ vars.plats = { "linuxppc", "linuxmips", "msdos86", + "msdos386", "osx386", "osxppc", "pc86", diff --git a/plat/msdos/include/ack/plat.h b/plat/msdos/include/ack/plat.h new file mode 100644 index 000000000..4343f1cf8 --- /dev/null +++ b/plat/msdos/include/ack/plat.h @@ -0,0 +1,11 @@ +/* $Source$ + * $State$ + * $Revision$ + */ + +#ifndef _ACK_PLAT_H +#define _ACK_PLAT_H + +#define ACKCONF_WANT_O_TEXT_O_BINARY 1 + +#endif diff --git a/plat/msdos/include/build.lua b/plat/msdos/include/build.lua new file mode 100644 index 000000000..6ae480041 --- /dev/null +++ b/plat/msdos/include/build.lua @@ -0,0 +1,24 @@ +include("plat/build.lua") + +headermap = {} +packagemap = {} + +local function addheader(h) + headermap[h] = "./"..h + packagemap["$(PLATIND)/msdos86/include/"..h] = "./"..h +end + +addheader("ack/plat.h") +addheader("sys/types.h") + +acklibrary { + name = "headers", + hdrs = headermap +} + +installable { + name = "pkg", + map = packagemap +} + + diff --git a/plat/msdos/include/sys/types.h b/plat/msdos/include/sys/types.h new file mode 100644 index 000000000..005f48eb0 --- /dev/null +++ b/plat/msdos/include/sys/types.h @@ -0,0 +1,9 @@ +#ifndef _SYS_TYPES_H +#define _SYS_TYPES_H + +typedef long pid_t; +typedef int mode_t; +typedef long time_t; +typedef long suseconds_t; + +#endif diff --git a/plat/msdos86/libsys/brk.c b/plat/msdos/libsys/brk.c similarity index 100% rename from plat/msdos86/libsys/brk.c rename to plat/msdos/libsys/brk.c diff --git a/plat/msdos/libsys/build.lua b/plat/msdos/libsys/build.lua new file mode 100644 index 000000000..d808fe894 --- /dev/null +++ b/plat/msdos/libsys/build.lua @@ -0,0 +1,28 @@ +bundle { + name = "srcs", + srcs = { + "./creat.c", + "./gettimeofday.c", + "./kill.c", + "./lseek.c", + "./open.c", + "./read.c", + "./setmode.c", + "./signal.c", + "./sys_fdmodes.c", + "./sys_getmode.c", + "./sys_initmain.c", + "./sys_iseof.c", + "./sys_seteof.c", + "./sys_seterrno.c", + "./sys_setmode.c", + "./write.c", + } +} + +bundle { + name = "headers", + srcs = { + "./libsys.h" + } +} diff --git a/plat/msdos86/libsys/creat.c b/plat/msdos/libsys/creat.c similarity index 100% rename from plat/msdos86/libsys/creat.c rename to plat/msdos/libsys/creat.c diff --git a/plat/msdos86/libsys/gettimeofday.c b/plat/msdos/libsys/gettimeofday.c similarity index 100% rename from plat/msdos86/libsys/gettimeofday.c rename to plat/msdos/libsys/gettimeofday.c diff --git a/plat/msdos86/libsys/kill.c b/plat/msdos/libsys/kill.c similarity index 100% rename from plat/msdos86/libsys/kill.c rename to plat/msdos/libsys/kill.c diff --git a/plat/msdos86/libsys/libsys.h b/plat/msdos/libsys/libsys.h similarity index 100% rename from plat/msdos86/libsys/libsys.h rename to plat/msdos/libsys/libsys.h diff --git a/plat/msdos86/libsys/lseek.c b/plat/msdos/libsys/lseek.c similarity index 100% rename from plat/msdos86/libsys/lseek.c rename to plat/msdos/libsys/lseek.c diff --git a/plat/msdos86/libsys/open.c b/plat/msdos/libsys/open.c similarity index 100% rename from plat/msdos86/libsys/open.c rename to plat/msdos/libsys/open.c diff --git a/plat/msdos86/libsys/read.c b/plat/msdos/libsys/read.c similarity index 100% rename from plat/msdos86/libsys/read.c rename to plat/msdos/libsys/read.c diff --git a/plat/msdos86/libsys/setmode.c b/plat/msdos/libsys/setmode.c similarity index 100% rename from plat/msdos86/libsys/setmode.c rename to plat/msdos/libsys/setmode.c diff --git a/plat/msdos86/libsys/signal.c b/plat/msdos/libsys/signal.c similarity index 100% rename from plat/msdos86/libsys/signal.c rename to plat/msdos/libsys/signal.c diff --git a/plat/msdos86/libsys/sys_fdmodes.c b/plat/msdos/libsys/sys_fdmodes.c similarity index 100% rename from plat/msdos86/libsys/sys_fdmodes.c rename to plat/msdos/libsys/sys_fdmodes.c diff --git a/plat/msdos86/libsys/sys_getmode.c b/plat/msdos/libsys/sys_getmode.c similarity index 100% rename from plat/msdos86/libsys/sys_getmode.c rename to plat/msdos/libsys/sys_getmode.c diff --git a/plat/msdos86/libsys/sys_initmain.c b/plat/msdos/libsys/sys_initmain.c similarity index 100% rename from plat/msdos86/libsys/sys_initmain.c rename to plat/msdos/libsys/sys_initmain.c diff --git a/plat/msdos86/libsys/sys_iseof.c b/plat/msdos/libsys/sys_iseof.c similarity index 100% rename from plat/msdos86/libsys/sys_iseof.c rename to plat/msdos/libsys/sys_iseof.c diff --git a/plat/msdos86/libsys/sys_seteof.c b/plat/msdos/libsys/sys_seteof.c similarity index 100% rename from plat/msdos86/libsys/sys_seteof.c rename to plat/msdos/libsys/sys_seteof.c diff --git a/plat/msdos86/libsys/sys_seterrno.c b/plat/msdos/libsys/sys_seterrno.c similarity index 100% rename from plat/msdos86/libsys/sys_seterrno.c rename to plat/msdos/libsys/sys_seterrno.c diff --git a/plat/msdos86/libsys/sys_setmode.c b/plat/msdos/libsys/sys_setmode.c similarity index 100% rename from plat/msdos86/libsys/sys_setmode.c rename to plat/msdos/libsys/sys_setmode.c diff --git a/plat/msdos86/libsys/write.c b/plat/msdos/libsys/write.c similarity index 100% rename from plat/msdos86/libsys/write.c rename to plat/msdos/libsys/write.c diff --git a/plat/msdos386/boot.s b/plat/msdos386/boot.s new file mode 100644 index 000000000..451291b13 --- /dev/null +++ b/plat/msdos386/boot.s @@ -0,0 +1,170 @@ +# +! $Source$ +! $State$ +! $Revision$ + +! Declare segments (the order is important). + +.sect .text +.sect .rom +.sect .data +.sect .bss + +.sect .text +.use16 + +#define STACK_BUFFER 128 /* number of bytes to leave for stack */ + +begtext: + ! Make sure we are running under MS-DOS 2 or above. + ! + ! While at it, also remember the actual DOS version, so that we know + ! whether DOS gives us the program's name in the environment + ! segment. (DOS 3+ does; DOS 2.x does not.) + movb ah, 0x30 + int 0x21 + cbw + cmpb al, 2 + xchg bp, ax + jnc ok_sys + + mov dx, bad_sys_msg +dos_msg: + movb ah, 9 + int 0x21 + ret + +ok_sys: + ! Resize the program's memory control block (MCB) to cover only the + ! program's near code and data space. Use the starting sp value as + ! a guide to how much memory we can grab. Abort on any failure. + ! + ! As a side effect, this also frees up any memory allocated to our + ! program beyond 64 KiB. (The freed memory can possibly be used by + ! e.g. child processes, in the future.) + ! + ! Also check that we have some space between the BSS end and the + ! starting sp. + cmp sp, endbss+STACK_BUFFER + jb no_room + + movb ah, 0x4a + mov bx, sp + movb cl, 4 + shr bx, cl + inc bx + int 0x21 + jc no_room + + ! Clear BSS. + mov di, begbss + mov cx, endbss+1 + sub cx, di + shr cx, 1 + xor ax, ax + cld + rep stosw + + ! Get the size of the environment variables plus (if present) the + ! program name. Also count the number of environment variables. + xor di, di + mov es, 0x002C(di) + ! ax = 0 from above + cwd ! dx = count of env. vars. + ! cx = 0 from above + dec cx ! cx = max. str. bytes to scan + scasb ! handle special case of empty env. + jz is_empty_env +size_env: + inc dx + repnz scasb + scasb + jnz size_env +is_empty_env: + cmp bp, 2 + jz no_argv0 + scasw + repnz scasb +no_argv0: + + ! Copy out the environment variables and (possibly) program name + ! onto the stack. + mov si, di + dec si + std +copy_env: + and si, -2 + eseg lodsw + push ax + jnz copy_env + mov cx, sp + + ! Reset DF and es properly. + cld + push ss + pop es + + ! Reserve space for argc and the argv and envp pointers on the + ! stack. These will be passed to __m_a_i_n later. + sub sp, 6 + mov ax, sp + + ! Build up argc, argv[], and envp[]. + push ax ! output buffer for argc, argv, envp + push bp ! MS-DOS version + push cx ! env. string data + push dx ! count of env. vars. + mov ax, 0x0080 + push ax ! raw command line + call __sys_initmain + add sp, 10 + + ! Bail out if something went wrong. + test ax, ax + jnz no_room + + ! argc, argv, and envp are now at the stack top. Now go. + call __m_a_i_n + add sp, 6 + push ax + call _exit + +no_room: + mov dx, no_room_msg + call dos_msg + movb al, -1 + jmp al_exit + + ! Exit. +.define __exit +.extern __exit +.define EXIT +.extern EXIT +__exit: +EXIT: + pop bx + pop ax +al_exit: + movb ah, 0x4c + int 0x21 + +! Define symbols at the beginning of our various segments, so that we can find +! them. (Except .text, which has already been done.) + +.define begtext, begdata, begbss +.sect .data; begdata: +.sect .rom; begrom: +.sect .bss; begbss: + +.sect .rom + +! Some text messages. +bad_sys_msg: .ascii 'Bad DOS$' +no_room_msg: .ascii 'No room$' + +! Some magic data. All EM systems need these. + +.define .trppc, .ignmask, _errno +.comm .trppc, 4 +.comm .ignmask, 4 +.comm _errno, 4 diff --git a/plat/msdos386/build-pkg.lua b/plat/msdos386/build-pkg.lua new file mode 100644 index 000000000..98cce47cc --- /dev/null +++ b/plat/msdos386/build-pkg.lua @@ -0,0 +1,25 @@ +include("plat/build.lua") + +ackfile { + name = "boot", + srcs = { "./boot.s" }, + vars = { plat = "msdos386" } +} + +build_plat_libs { + name = "libs", + arch = "i386", + plat = "msdos386", +} + +installable { + name = "pkg", + map = { + "+tools", + "+libs", + "./include+pkg", + ["$(PLATIND)/msdos386/boot.o"] = "+boot", + ["$(PLATIND)/msdos386/libsys.a"] = "./libsys+lib", + } +} + diff --git a/plat/msdos386/build-tools.lua b/plat/msdos386/build-tools.lua new file mode 100644 index 000000000..d28aee904 --- /dev/null +++ b/plat/msdos386/build-tools.lua @@ -0,0 +1,21 @@ +include("plat/build.lua") + +build_as { + name = "as", + arch = "i386", +} + +build_ncg { + name = "ncg", + arch = "i386", +} + +return installable { + name = "tools", + map = { + ["$(PLATDEP)/msdos386/as"] = "+as", + ["$(PLATDEP)/msdos386/ncg"] = "+ncg", + ["$(PLATIND)/descr/msdos386"] = "./descr", + "util/opt+pkg", + } +} diff --git a/plat/msdos386/descr b/plat/msdos386/descr new file mode 100644 index 000000000..f6559471e --- /dev/null +++ b/plat/msdos386/descr @@ -0,0 +1,77 @@ +var w=4 +var wa=2 +var p=4 +var pa=2 +var s=2 +var sa=2 +var l=4 +var la=2 +var f=4 +var fa=2 +var d=8 +var da=2 +var x=8 +var xa=2 +var ARCH=i386 +var PLATFORM=msdos386 +var PLATFORMDIR={EM}/share/ack/{PLATFORM} +var CPP_F=-D__MSDOS__ -D__DOS__ -D_DOS +var ALIGN=-a0:2 -a1:2 -a2:2 -a3:2 +var MACHOPT_F=-m8 +var EGO_PLAT_FLAGS=-M{EM}/share/ack/ego/{ARCH}.descr + +# Override the setting in fe so that files compiled for this platform can see +# the platform-specific headers. + +var C_INCLUDES=-I{PLATFORMDIR}/include -I{EM}/share/ack/include/ansi + +name be + from .m.g + to .s + program {EM}/lib/ack/{PLATFORM}/ncg + args < + stdout + need .e +end +name as + from .s.so + to .o + program {EM}/lib/ack/{PLATFORM}/as + args - -o > < + prep cond +end +name led + from .o.a + to .out + program {EM}/lib/ack/em_led + mapflag -l* LNAME={PLATFORMDIR}/lib* + mapflag -fp FLOATS={EM}/{ILIB}fp + args {ALIGN} {SEPID} \ + ({RTS}:.b=-u _i_main) \ + (.e:{HEAD}={PLATFORMDIR}/boot.o) \ + ({RTS}:.ocm.bas.b={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.c={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.mod={PLATFORMDIR}/modula2.o) \ + ({RTS}:.p={PLATFORMDIR}/pascal.o) \ + -o > < \ + (.p:{TAIL}={PLATFORMDIR}/libpascal.a) \ + (.b:{TAIL}={PLATFORMDIR}/libb.a) \ + (.bas:{TAIL}={PLATFORMDIR}/libbasic.a) \ + (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ + (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ + (.ocm.bas.mod.b.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ + {FLOATS?} \ + (.e:{TAIL}={PLATFORMDIR}/libem.a \ + {PLATFORMDIR}/libsys.a \ + {PLATFORMDIR}/libc.a \ + {PLATFORMDIR}/libem.a \ + {PLATFORMDIR}/libend.a) + linker +end +name cv + from .out + to .exe + program {EM}/bin/aslod + args < > + outfile msdos386.exe +end diff --git a/plat/msdos386/include/ack/plat.h b/plat/msdos386/include/ack/plat.h new file mode 100644 index 000000000..c0d1b9fff --- /dev/null +++ b/plat/msdos386/include/ack/plat.h @@ -0,0 +1,6 @@ +#ifndef _ACK_PLAT_H +#define _ACK_PLAT_H + +#define ACKCONF_WANT_O_TEXT_O_BINARY 1 + +#endif diff --git a/plat/msdos386/include/build.lua b/plat/msdos386/include/build.lua new file mode 100644 index 000000000..693abd0c1 --- /dev/null +++ b/plat/msdos386/include/build.lua @@ -0,0 +1,24 @@ +include("plat/build.lua") + +headermap = {} +packagemap = {} + +local function addheader(h) + headermap[h] = "./"..h + packagemap["$(PLATIND)/msdos386/include/"..h] = "./"..h +end + +addheader("ack/plat.h") +addheader("sys/types.h") + +acklibrary { + name = "headers", + hdrs = headermap +} + +installable { + name = "pkg", + map = packagemap +} + + diff --git a/plat/msdos386/include/sys/types.h b/plat/msdos386/include/sys/types.h new file mode 100644 index 000000000..005f48eb0 --- /dev/null +++ b/plat/msdos386/include/sys/types.h @@ -0,0 +1,9 @@ +#ifndef _SYS_TYPES_H +#define _SYS_TYPES_H + +typedef long pid_t; +typedef int mode_t; +typedef long time_t; +typedef long suseconds_t; + +#endif diff --git a/plat/msdos386/libsys/build.lua b/plat/msdos386/libsys/build.lua new file mode 100644 index 000000000..c2ae13f52 --- /dev/null +++ b/plat/msdos386/libsys/build.lua @@ -0,0 +1,47 @@ +acklibrary { + name = "lib", + srcs = { +-- "./brk.c", +-- "./close.s", +-- "./creat.c", +-- "./errno.s", +-- "./getpid.s", +-- "./gettimeofday.c", +-- "./_hol0.s", +-- "./isatty.s", +-- "./kill.c", +-- "./lseek.c", +-- "./open.c", +-- "./read.c", +-- "./setmode.c", +-- "./signal.c", +-- "./sys_exists.s", +-- "./sys_fdmodes.c", +-- "./sys_getdate.s", +-- "./sys_getmode.c", +-- "./sys_gettime.s", +-- "./sys_initmain.c", +-- "./sys_iseof.c", +-- "./sys_isopen.s", +-- "./sys_isreadyr.s", +-- "./sys_rawcreat.s", +-- "./sys_rawlseek.s", +-- "./sys_rawopen.s", +-- "./sys_rawrw.s", +-- "./sys_seteof.c", +-- "./sys_seterrno.c", +-- "./sys_setmode.c", +-- "./sys_xret.s", +-- "./unlink.s", + "plat/msdos/libsys+srcs", + }, + deps = { + "lang/cem/libcc.ansi/headers+headers", + "plat/msdos386/include+headers", + "plat/msdos/libsys+headers", + }, + vars = { + plat = "msdos386" + } +} + diff --git a/plat/msdos86/libsys/build.lua b/plat/msdos86/libsys/build.lua index eddbbf262..e7d9b8fc7 100644 --- a/plat/msdos86/libsys/build.lua +++ b/plat/msdos86/libsys/build.lua @@ -1,43 +1,28 @@ acklibrary { name = "lib", srcs = { - "./brk.c", "./close.s", - "./creat.c", "./errno.s", "./getpid.s", - "./gettimeofday.c", "./_hol0.s", "./isatty.s", - "./kill.c", - "./lseek.c", - "./open.c", - "./read.c", - "./setmode.c", - "./signal.c", "./sys_exists.s", - "./sys_fdmodes.c", "./sys_getdate.s", - "./sys_getmode.c", "./sys_gettime.s", - "./sys_initmain.c", - "./sys_iseof.c", "./sys_isopen.s", "./sys_isreadyr.s", "./sys_rawcreat.s", "./sys_rawlseek.s", "./sys_rawopen.s", "./sys_rawrw.s", - "./sys_seteof.c", - "./sys_seterrno.c", - "./sys_setmode.c", "./sys_xret.s", "./unlink.s", - "./write.c", + "plat/msdos/libsys+srcs", }, deps = { "lang/cem/libcc.ansi/headers+headers", "plat/msdos86/include+headers", + "plat/msdos/libsys+headers", }, vars = { plat = "msdos86" From b81ac5e2c32ca6ffb876855fc10aa4a6e3f74e93 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 7 Aug 2022 22:10:08 +0200 Subject: [PATCH 03/20] Cut-and-paste the msdos86 libsys so the msdos386 stuff now at least builds. --- plat/msdos386/libsys/_hol0.s | 19 +++++++++ plat/{msdos => msdos386}/libsys/brk.c | 0 plat/msdos386/libsys/build.lua | 49 ++++++++-------------- plat/msdos386/libsys/close.s | 23 +++++++++++ plat/msdos386/libsys/errno.s | 28 +++++++++++++ plat/msdos386/libsys/getpid.s | 45 ++++++++++++++++++++ plat/msdos386/libsys/isatty.s | 37 +++++++++++++++++ plat/msdos386/libsys/rename.s | 26 ++++++++++++ plat/msdos386/libsys/sys_exists.s | 25 ++++++++++++ plat/msdos386/libsys/sys_getdate.s | 25 ++++++++++++ plat/msdos386/libsys/sys_gettime.s | 25 ++++++++++++ plat/msdos386/libsys/sys_isopen.s | 26 ++++++++++++ plat/msdos386/libsys/sys_isreadyr.s | 28 +++++++++++++ plat/msdos386/libsys/sys_rawcreat.s | 24 +++++++++++ plat/msdos386/libsys/sys_rawlseek.s | 26 ++++++++++++ plat/msdos386/libsys/sys_rawopen.s | 24 +++++++++++ plat/msdos386/libsys/sys_rawrw.s | 33 +++++++++++++++ plat/msdos386/libsys/sys_xret.s | 41 +++++++++++++++++++ plat/msdos386/libsys/unlink.s | 23 +++++++++++ plat/msdos86/libsys/brk.c | 59 +++++++++++++++++++++++++++ plat/msdos86/libsys/build.lua | 1 + 21 files changed, 555 insertions(+), 32 deletions(-) create mode 100644 plat/msdos386/libsys/_hol0.s rename plat/{msdos => msdos386}/libsys/brk.c (100%) create mode 100644 plat/msdos386/libsys/close.s create mode 100644 plat/msdos386/libsys/errno.s create mode 100644 plat/msdos386/libsys/getpid.s create mode 100644 plat/msdos386/libsys/isatty.s create mode 100644 plat/msdos386/libsys/rename.s create mode 100644 plat/msdos386/libsys/sys_exists.s create mode 100644 plat/msdos386/libsys/sys_getdate.s create mode 100644 plat/msdos386/libsys/sys_gettime.s create mode 100644 plat/msdos386/libsys/sys_isopen.s create mode 100644 plat/msdos386/libsys/sys_isreadyr.s create mode 100644 plat/msdos386/libsys/sys_rawcreat.s create mode 100644 plat/msdos386/libsys/sys_rawlseek.s create mode 100644 plat/msdos386/libsys/sys_rawopen.s create mode 100644 plat/msdos386/libsys/sys_rawrw.s create mode 100644 plat/msdos386/libsys/sys_xret.s create mode 100644 plat/msdos386/libsys/unlink.s create mode 100644 plat/msdos86/libsys/brk.c diff --git a/plat/msdos386/libsys/_hol0.s b/plat/msdos386/libsys/_hol0.s new file mode 100644 index 000000000..f01566fe8 --- /dev/null +++ b/plat/msdos386/libsys/_hol0.s @@ -0,0 +1,19 @@ +# +! $Source$ +! $State$ +! $Revision$ + +! Declare segments (the order is important). + +.sect .text +.sect .rom +.sect .data +.sect .bss + +.sect .bss + +! This data block is used to store information about the current line number +! and file. + +.define hol0 +.comm hol0, 8 diff --git a/plat/msdos/libsys/brk.c b/plat/msdos386/libsys/brk.c similarity index 100% rename from plat/msdos/libsys/brk.c rename to plat/msdos386/libsys/brk.c diff --git a/plat/msdos386/libsys/build.lua b/plat/msdos386/libsys/build.lua index 2725c0f70..70c7eaa17 100644 --- a/plat/msdos386/libsys/build.lua +++ b/plat/msdos386/libsys/build.lua @@ -1,39 +1,24 @@ acklibrary { name = "lib", srcs = { + "./brk.c", + "./close.s", + "./errno.s", + "./getpid.s", + "./_hol0.s", + "./isatty.s", "./rename.s", --- "./brk.c", --- "./close.s", --- "./creat.c", --- "./errno.s", --- "./getpid.s", --- "./gettimeofday.c", --- "./_hol0.s", --- "./isatty.s", --- "./kill.c", --- "./lseek.c", --- "./open.c", --- "./read.c", --- "./setmode.c", --- "./signal.c", --- "./sys_exists.s", --- "./sys_fdmodes.c", --- "./sys_getdate.s", --- "./sys_getmode.c", --- "./sys_gettime.s", --- "./sys_initmain.c", --- "./sys_iseof.c", --- "./sys_isopen.s", --- "./sys_isreadyr.s", --- "./sys_rawcreat.s", --- "./sys_rawlseek.s", --- "./sys_rawopen.s", --- "./sys_rawrw.s", --- "./sys_seteof.c", --- "./sys_seterrno.c", --- "./sys_setmode.c", --- "./sys_xret.s", --- "./unlink.s", + "./sys_exists.s", + "./sys_getdate.s", + "./sys_gettime.s", + "./sys_isopen.s", + "./sys_isreadyr.s", + "./sys_rawcreat.s", + "./sys_rawlseek.s", + "./sys_rawopen.s", + "./sys_rawrw.s", + "./sys_xret.s", + "./unlink.s", "plat/msdos/libsys+srcs", }, deps = { diff --git a/plat/msdos386/libsys/close.s b/plat/msdos386/libsys/close.s new file mode 100644 index 000000000..b8c2f8a15 --- /dev/null +++ b/plat/msdos386/libsys/close.s @@ -0,0 +1,23 @@ +# +! $Source$ +! $State$ +! $Revision$ + +! Declare segments (the order is important). + +.sect .text +.sect .rom +.sect .data +.sect .bss + +.sect .text + +! Close a file. + +.define _close +_close: + mov bx, sp + mov bx, 2(bx) + movb ah, 0x3E + int 0x21 + jmp .sys_zret diff --git a/plat/msdos386/libsys/errno.s b/plat/msdos386/libsys/errno.s new file mode 100644 index 000000000..9858d2640 --- /dev/null +++ b/plat/msdos386/libsys/errno.s @@ -0,0 +1,28 @@ +# +! $Source$ +! $State$ +! $Revision$ + +! Declare segments (the order is important). + +.sect .text +.sect .rom +.sect .data +.sect .bss + +#define D(e) .define e; e + +.sect .data + +! Define various ACK error numbers. Note that these are *not* ANSI C +! errnos, and are used for different purposes. + +D(ERANGE) = 1 +D(ESET) = 2 +D(EIDIVZ) = 6 +D(EHEAP) = 17 +D(EILLINS) = 18 +D(EODDZ) = 19 +D(ECASE) = 20 +D(EBADMON) = 25 + diff --git a/plat/msdos386/libsys/getpid.s b/plat/msdos386/libsys/getpid.s new file mode 100644 index 000000000..5aa80638b --- /dev/null +++ b/plat/msdos386/libsys/getpid.s @@ -0,0 +1,45 @@ +# +! $Source$ +! $State$ +! $Revision$ + +! Copyright (c) 2021--2022 TK Chia +! +! The authors hereby grant permission to use, copy, modify, distribute, +! and license this software and its documentation for any purpose, provided +! that existing copyright notices are retained in all copies and that this +! notice is included verbatim in any distributions. No written agreement, +! license, or royalty fee is required for any of the authorized uses. +! Modifications to this software may be copyrighted by their authors +! and need not follow the licensing terms described here, provided that +! the new terms are clearly indicated on the first page of each file where +! they apply. + +! Declare segments (the order is important). + +.sect .text +.sect .rom +.sect .data +.sect .bss + +.sect .text + +! Get the current process identifier. For MS-DOS, use the Program Segment +! Prefix (PSP) segment as the PID, unless the system supports an actual +! `getpid' syscall, e.g. European MS-DOS 4.0. +! +! (Note that pid_t is a 32-bit type. This is to allow for PSP segments and +! MS-DOS PIDs above 0x7FFF.) + +.define _getpid +_getpid: + movb ah, 0x87 + stc + int 0x21 + jnc .eur_dos + movb ah, 0x51 + int 0x21 + xchg bx, ax +.eur_dos: + xor dx, dx + ret diff --git a/plat/msdos386/libsys/isatty.s b/plat/msdos386/libsys/isatty.s new file mode 100644 index 000000000..bd2e195e6 --- /dev/null +++ b/plat/msdos386/libsys/isatty.s @@ -0,0 +1,37 @@ +# +! $Source$ +! $State$ +! $Revision$ + +! Declare segments (the order is important). + +.sect .text +.sect .rom +.sect .data +.sect .bss + +.sect .text + +! Say whether a given file descriptor number refers to a terminal. + +.define _isatty +_isatty: + mov bx, sp + mov bx, 2(bx) + mov ax, 0x4400 + int 0x21 + jc error + testb dl, dl + jz not_tty + mov ax, 1 + ret +not_tty: + mov (_errno), 25 ! ENOTTY +not_tty_2: + xor ax, ax + ret +error: + push ax + call __sys_seterrno + pop cx + jmp not_tty_2 diff --git a/plat/msdos386/libsys/rename.s b/plat/msdos386/libsys/rename.s new file mode 100644 index 000000000..edb14266b --- /dev/null +++ b/plat/msdos386/libsys/rename.s @@ -0,0 +1,26 @@ +# +! $Source$ +! $State$ +! $Revision$ + +! Declare segments (the order is important). + +.sect .text +.sect .rom +.sect .data +.sect .bss + +.sect .text + +! Rename a file. + +.define _rename +_rename: + mov bx, sp + push di + mov dx, 2(bx) + mov di, 4(bx) + movb ah, 0x56 + int 0x21 + pop di + jmp .sys_zret diff --git a/plat/msdos386/libsys/sys_exists.s b/plat/msdos386/libsys/sys_exists.s new file mode 100644 index 000000000..e282ef687 --- /dev/null +++ b/plat/msdos386/libsys/sys_exists.s @@ -0,0 +1,25 @@ +# +! $Source$ +! $State$ +! $Revision$ + +! Declare segments (the order is important). + +.sect .text +.sect .rom +.sect .data +.sect .bss + +.sect .text + +! Say whether a file exists with the given name. + +.define __sys_exists +__sys_exists: + mov bx, sp + mov dx, 2(bx) + mov ax, 0x4300 + int 0x21 + sbb ax, ax + inc ax + ret diff --git a/plat/msdos386/libsys/sys_getdate.s b/plat/msdos386/libsys/sys_getdate.s new file mode 100644 index 000000000..41d69fc85 --- /dev/null +++ b/plat/msdos386/libsys/sys_getdate.s @@ -0,0 +1,25 @@ +# +! $Source$ +! $State$ +! $Revision$ + +! Declare segments (the order is important). + +.sect .text +.sect .rom +.sect .data +.sect .bss + +.sect .text + +! Get the current system date from MS-DOS. + +.define __sys_getdate +__sys_getdate: + movb ah, 0x2a + int 0x21 + mov bx, sp + mov bx, 2(bx) + mov (bx), dx + mov 2(bx), cx + ret diff --git a/plat/msdos386/libsys/sys_gettime.s b/plat/msdos386/libsys/sys_gettime.s new file mode 100644 index 000000000..d062fad8d --- /dev/null +++ b/plat/msdos386/libsys/sys_gettime.s @@ -0,0 +1,25 @@ +# +! $Source$ +! $State$ +! $Revision$ + +! Declare segments (the order is important). + +.sect .text +.sect .rom +.sect .data +.sect .bss + +.sect .text + +! Get the current system time from MS-DOS. + +.define __sys_gettime +__sys_gettime: + movb ah, 0x2c + int 0x21 + mov bx, sp + mov bx, 2(bx) + mov (bx), cx + mov 2(bx), dx + ret diff --git a/plat/msdos386/libsys/sys_isopen.s b/plat/msdos386/libsys/sys_isopen.s new file mode 100644 index 000000000..5ce49ed45 --- /dev/null +++ b/plat/msdos386/libsys/sys_isopen.s @@ -0,0 +1,26 @@ +# +! $Source$ +! $State$ +! $Revision$ + +! Declare segments (the order is important). + +.sect .text +.sect .rom +.sect .data +.sect .bss + +.sect .text + +! Say whether a given file descriptor number refers to a valid open file +! descriptor. + +.define __sys_isopen +__sys_isopen: + mov bx, sp + mov bx, 2(bx) + mov ax, 0x4400 + int 0x21 + sbb ax, ax + inc ax + ret diff --git a/plat/msdos386/libsys/sys_isreadyr.s b/plat/msdos386/libsys/sys_isreadyr.s new file mode 100644 index 000000000..b5d0800ee --- /dev/null +++ b/plat/msdos386/libsys/sys_isreadyr.s @@ -0,0 +1,28 @@ +# +! $Source$ +! $State$ +! $Revision$ + +! Declare segments (the order is important). + +.sect .text +.sect .rom +.sect .data +.sect .bss + +.sect .text + +! Say whether a file descriptor is ready for input, i.e. reading from the +! fd will immediately return something. + +.define __sys_isreadyr +__sys_isreadyr: + mov bx, sp + mov ax, 0x4406 + mov bx, 2(bx) + int 0x21 + jnc ok + movb al, 0 +ok: + cbw + ret diff --git a/plat/msdos386/libsys/sys_rawcreat.s b/plat/msdos386/libsys/sys_rawcreat.s new file mode 100644 index 000000000..67bc34e59 --- /dev/null +++ b/plat/msdos386/libsys/sys_rawcreat.s @@ -0,0 +1,24 @@ +# +! $Source$ +! $State$ +! $Revision$ + +! Declare segments (the order is important). + +.sect .text +.sect .rom +.sect .data +.sect .bss + +.sect .text + +! Create or truncate a file. + +.define __sys_rawcreat +__sys_rawcreat: + movb ah, 0x3c + mov bx, sp + mov dx, 2(bx) + mov cx, 4(bx) + int 0x21 + jmp .sys_axret diff --git a/plat/msdos386/libsys/sys_rawlseek.s b/plat/msdos386/libsys/sys_rawlseek.s new file mode 100644 index 000000000..992c4c655 --- /dev/null +++ b/plat/msdos386/libsys/sys_rawlseek.s @@ -0,0 +1,26 @@ +# +! $Source$ +! $State$ +! $Revision$ + +! Declare segments (the order is important). + +.sect .text +.sect .rom +.sect .data +.sect .bss + +.sect .text + +! Move the current file position for a file descriptor. + +.define __sys_rawlseek +__sys_rawlseek: + movb ah, 0x42 + mov bx, sp + mov dx, 4(bx) + mov cx, 6(bx) + movb al, 8(bx) + mov bx, 2(bx) + int 0x21 + jmp .sys_dxaxret diff --git a/plat/msdos386/libsys/sys_rawopen.s b/plat/msdos386/libsys/sys_rawopen.s new file mode 100644 index 000000000..301e2fded --- /dev/null +++ b/plat/msdos386/libsys/sys_rawopen.s @@ -0,0 +1,24 @@ +# +! $Source$ +! $State$ +! $Revision$ + +! Declare segments (the order is important). + +.sect .text +.sect .rom +.sect .data +.sect .bss + +.sect .text + +! Open an existing file. + +.define __sys_rawopen +__sys_rawopen: + movb ah, 0x3d + mov bx, sp + mov dx, 2(bx) + movb al, 4(bx) + int 0x21 + jmp .sys_axret diff --git a/plat/msdos386/libsys/sys_rawrw.s b/plat/msdos386/libsys/sys_rawrw.s new file mode 100644 index 000000000..a306d6528 --- /dev/null +++ b/plat/msdos386/libsys/sys_rawrw.s @@ -0,0 +1,33 @@ +# +! $Source$ +! $State$ +! $Revision$ + +! Declare segments (the order is important). + +.sect .text +.sect .rom +.sect .data +.sect .bss + +.sect .text + +! Read/write bytes to/to a file descriptor. These routines do not do any +! translation between CRLF and LF line endings. +! +! Note that, for MS-DOS, a raw "write" request of zero bytes will truncate +! (or extend) the file to the current file position. + +.define __sys_rawread +__sys_rawread: + movb ah, 0x3f + .data1 0x3d ! eat up the next instruction +.define __sys_rawwrite +__sys_rawwrite: + movb ah, 0x40 + mov bx, sp + mov dx, 4(bx) + mov cx, 6(bx) + mov bx, 2(bx) + int 0x21 + jmp .sys_axret diff --git a/plat/msdos386/libsys/sys_xret.s b/plat/msdos386/libsys/sys_xret.s new file mode 100644 index 000000000..57f407ef4 --- /dev/null +++ b/plat/msdos386/libsys/sys_xret.s @@ -0,0 +1,41 @@ +# +! $Source$ +! $State$ +! $Revision$ + +! Declare segments (the order is important). + +.sect .text +.sect .rom +.sect .data +.sect .bss + +.sect .text + +! .sys_zret: if the carry flag is set, then set `errno' from the DOS error +! code in ax, and return a shortword -1. If the carry flag is clear, just +! return a shortword zero. +! +! .sys_axret: if the carry flag is set, then set `errno' from the DOS error +! code in ax, and return a shortword -1. If the carry flag is clear, just +! return ax as a return value. +! +! .sys_dxaxret: same as .sys_axret, but return a longword -1 or dx:ax as a +! return value. + +.extern .sys_zret +.extern .sys_axret +.extern .sys_dxaxret +.sys_zret: + jc error + xor ax, ax +no_error: + ret +.sys_axret: +.sys_dxaxret: + jnc no_error +error: + push ax + call __sys_seterrno + pop cx + ret diff --git a/plat/msdos386/libsys/unlink.s b/plat/msdos386/libsys/unlink.s new file mode 100644 index 000000000..912f6958d --- /dev/null +++ b/plat/msdos386/libsys/unlink.s @@ -0,0 +1,23 @@ +# +! $Source$ +! $State$ +! $Revision$ + +! Declare segments (the order is important). + +.sect .text +.sect .rom +.sect .data +.sect .bss + +.sect .text + +! Remove a file. + +.define _unlink +_unlink: + mov bx, sp + mov dx, 2(bx) + movb ah, 0x41 + int 0x21 + jmp .sys_zret diff --git a/plat/msdos86/libsys/brk.c b/plat/msdos86/libsys/brk.c new file mode 100644 index 000000000..ab333e550 --- /dev/null +++ b/plat/msdos86/libsys/brk.c @@ -0,0 +1,59 @@ +/* $Source$ + * $State$ + * $Revision$ + */ + +#include +#include +#include +#include "libsys.h" + +#define STACK_BUFFER 128 /* number of bytes to leave for stack */ + +extern char _end[1]; +static char* current = _end; + +int brk(void* newend) +{ + /* This variable is used to figure out the current stack pointer, + * by taking its address. */ + char dummy; + char* p = newend; + + if ((p > (&dummy - STACK_BUFFER)) || + (p < _end)) + { + errno = ENOMEM; + return -1; + } + + current = p; + return 0; +} + +void* sbrk(int increment) +{ + char* old; + char* new; + + if (increment == 0) + return current; + + old = current; + + new = old + increment; + + if ((increment > 0) && (new <= old)) + goto out_of_memory; + else if ((increment < 0) && (new >= old)) + goto out_of_memory; + + if (brk(new) < 0) + goto out_of_memory; + + return old; + +out_of_memory: + errno = ENOMEM; + return OUT_OF_MEMORY; +} diff --git a/plat/msdos86/libsys/build.lua b/plat/msdos86/libsys/build.lua index 58bf3e6e5..96988002d 100644 --- a/plat/msdos86/libsys/build.lua +++ b/plat/msdos86/libsys/build.lua @@ -1,6 +1,7 @@ acklibrary { name = "lib", srcs = { + "./brk.c", "./close.s", "./errno.s", "./getpid.s", From f2a49ff3ab91e7c54de7763c144fcfe8fc80733d Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 8 Aug 2022 00:01:06 +0200 Subject: [PATCH 04/20] msdos86 actually emits .COM files. --- plat/msdos86/descr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plat/msdos86/descr b/plat/msdos86/descr index 333bb671b..2ef1724ee 100644 --- a/plat/msdos86/descr +++ b/plat/msdos86/descr @@ -84,5 +84,5 @@ name cv mapflag -i LOD=amzlod program {EM}/bin/{LOD} args < > - outfile msdos86.exe + outfile msdos86.com end From 3716d49cd9d340951f7e6ab878b2959fcdc1b730 Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 8 Aug 2022 22:02:51 +0200 Subject: [PATCH 05/20] Allow arithmetic on variable values. --- mach/proto/as/comm7.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mach/proto/as/comm7.c b/mach/proto/as/comm7.c index 9b93139d4..969d0d84a 100644 --- a/mach/proto/as/comm7.c +++ b/mach/proto/as/comm7.c @@ -86,6 +86,9 @@ char* remember(char* s) int combine(int typ1, int typ2, int op) { + typ1 &= ~S_VAR; + typ2 &= ~S_VAR; + switch (op) { case '+': @@ -112,6 +115,7 @@ int combine(int typ1, int typ2, int op) return (S_ABS); break; } + fprintf(stderr, "typ1=%d typ2=%d pass=%d\n", typ1, typ2, pass); if (pass != PASS_1) serror("illegal operator"); return (S_UND); From 1e0961c679b33da0696a3efb0862f1c8dfa6a8cf Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 8 Aug 2022 22:03:12 +0200 Subject: [PATCH 06/20] Do enough of the boot stub to produce an EXE header and enter DPMI protected mode. --- plat/msdos386/boot.s | 333 +++++++++++++++++++++++++++++-------------- 1 file changed, 229 insertions(+), 104 deletions(-) diff --git a/plat/msdos386/boot.s b/plat/msdos386/boot.s index 451291b13..de46f54e8 100644 --- a/plat/msdos386/boot.s +++ b/plat/msdos386/boot.s @@ -12,141 +12,263 @@ .sect .text .use16 +exe_header: + .data2 0x5a4d ! magic number + .data2 0 ! number of bytes in last loadable page + .data2 exe_text_paras ! size of .exe, in pages + .data2 0 ! number of relocation entries + .data2 0 ! start of loadable area, in 16-byte paragraphs + .data2 exe_ram_paras ! required RAM size, in 16-byte paragraphs + .data2 0 ! maximum RAM siz, in 16-byte paragraphse + .data2 0 ! initial SS, relative to program + .data2 exe_stack ! initial SP + .data2 0 ! checksum (ignored) + .data2 exe_start ! initial IP + .data2 0 ! initial CS, relative to program + .data2 0 ! offset of relocation table + .data2 0 ! overlay number + +dpmi_edi = 0x00 +dpmi_esi = 0x04 +dpmi_ebp = 0x08 +dpmi_ebx = 0x10 +dpmi_edx = 0x14 +dpmi_ecx = 0x18 +dpmi_eax = 0x1c +dpmi_flags = 0x20 +dpmi_es = 0x22 +dpmi_ds = 0x24 +dpmi_fs = 0x26 +dpmi_gs = 0x28 +dpmi_ip = 0x2a +dpmi_cs = 0x2c +dpmi_sp = 0x2e +dpmi_ss = 0x30 + +dpmi_ps = 0x32 ! WORD: protected register segment +dpmi_rs = 0x34 ! WORD: real register segment +dpmi_psp = 0x36 ! WORD: PSP segment +dpmi_switch = 0x38 ! DWORD: far pointer of pmode switch routine + + .seek 0x3c +exe_start: + ! On entry, DS=ES=PSP. Make DS=CS, so we're running in tiny mode. + + push cs + pop ds + mov (dpmi_rs), ds + mov (dpmi_psp), es + + ! Initialise DPMI. + + mov ax, 0x1687 + int 0x2f + or ax, ax + jnz no_dpmi + mov (dpmi_switch+0), di ! write back PMODE switch routine + mov (dpmi_switch+2), es + or si, si ! do we need a DPMI private area? + jz 1f + + mov bx, si + movb ah, 0x48 + int 0x21 ! allocate memory from DOS + mov es, ax ! data area segment -> es +1: + ! Switch to protected mode. + + mov ax, 1 ! 32-bit app + callf (dpmi_switch) + jc no_pmode + + mov (dpmi_edx), go_msg + mov ax, (dpmi_rs) + mov (dpmi_ds), ax + mov (dpmi_eax+1), 9 + call int21 + mov ax, 0x4c00 + int 0x21 + + ! Simulate DOS interrupt bx. +int21: + mov bx, 0x21 +callint: + xor ax, ax + mov (dpmi_ss), ax ! zero stack: DPMI host allocates one. + mov (dpmi_sp), ax + push ds + pop es + mov di, ax + mov ax, 0x300 + int 0x31 ! simulate DOS interrupt + push cs + pop ds + ret + +no_pmode: ! Could not switch to protected mode. + mov dx, no_pmode_msg + jmp exit_with_error + +no_dpmi: + mov dx, no_dpmi_msg + ! fall through + +! Displays the message in dx and exits. +exit_with_error: + movb ah, 9 + int 0x21 ! print $-terminated string + mov ax, 0x4cff + int 0x21 ! terminate with error code al + + .use32 +start_32bit: + +go_msg: + .ascii "Go!$" +no_pmode_msg: + .ascii "Couldn't switch to protected mode$" +no_dpmi_msg: + .ascii "No DPMI$" + +exe_top: + +exe_stack = exe_top + 512 +exe_text_paras = [exe_top - exe_header + 511] / 512 +exe_ram_paras = [exe_stack - exe_top + 15] / 16 + #define STACK_BUFFER 128 /* number of bytes to leave for stack */ begtext: - ! Make sure we are running under MS-DOS 2 or above. - ! - ! While at it, also remember the actual DOS version, so that we know - ! whether DOS gives us the program's name in the environment - ! segment. (DOS 3+ does; DOS 2.x does not.) - movb ah, 0x30 - int 0x21 - cbw - cmpb al, 2 - xchg bp, ax - jnc ok_sys + ! Make sure we are running under MS-DOS 2 or above. + ! + ! While at it, also remember the actual DOS version, so that we know + ! whether DOS gives us the program's name in the environment + ! segment. (DOS 3+ does; DOS 2.x does not.) + movb ah, 0x30 + int 0x21 + cbw + cmpb al, 2 + xchg bp, ax + jnc ok_sys - mov dx, bad_sys_msg + mov dx, bad_sys_msg dos_msg: - movb ah, 9 - int 0x21 - ret + ret ok_sys: - ! Resize the program's memory control block (MCB) to cover only the - ! program's near code and data space. Use the starting sp value as - ! a guide to how much memory we can grab. Abort on any failure. - ! - ! As a side effect, this also frees up any memory allocated to our - ! program beyond 64 KiB. (The freed memory can possibly be used by - ! e.g. child processes, in the future.) - ! - ! Also check that we have some space between the BSS end and the - ! starting sp. - cmp sp, endbss+STACK_BUFFER - jb no_room + ! Resize the program's memory control block (MCB) to cover only the + ! program's near code and data space. Use the starting sp value as + ! a guide to how much memory we can grab. Abort on any failure. + ! + ! As a side effect, this also frees up any memory allocated to our + ! program beyond 64 KiB. (The freed memory can possibly be used by + ! e.g. child processes, in the future.) + ! + ! Also check that we have some space between the BSS end and the + ! starting sp. + cmp sp, endbss+STACK_BUFFER + jb no_room - movb ah, 0x4a - mov bx, sp - movb cl, 4 - shr bx, cl - inc bx - int 0x21 - jc no_room + movb ah, 0x4a + mov bx, sp + movb cl, 4 + shr bx, cl + inc bx + int 0x21 + jc no_room - ! Clear BSS. - mov di, begbss - mov cx, endbss+1 - sub cx, di - shr cx, 1 - xor ax, ax - cld - rep stosw + ! Clear BSS. + mov di, begbss + mov cx, endbss+1 + sub cx, di + shr cx, 1 + xor ax, ax + cld + rep stosw - ! Get the size of the environment variables plus (if present) the - ! program name. Also count the number of environment variables. - xor di, di - mov es, 0x002C(di) - ! ax = 0 from above - cwd ! dx = count of env. vars. - ! cx = 0 from above - dec cx ! cx = max. str. bytes to scan - scasb ! handle special case of empty env. - jz is_empty_env + ! Get the size of the environment variables plus (if present) the + ! program name. Also count the number of environment variables. + xor di, di + mov es, 0x002C(di) + ! ax = 0 from above + cwd ! dx = count of env. vars. + ! cx = 0 from above + dec cx ! cx = max. str. bytes to scan + scasb ! handle special case of empty env. + jz is_empty_env size_env: - inc dx - repnz scasb - scasb - jnz size_env + inc dx + repnz scasb + scasb + jnz size_env is_empty_env: - cmp bp, 2 - jz no_argv0 - scasw - repnz scasb + cmp bp, 2 + jz no_argv0 + scasw + repnz scasb no_argv0: - ! Copy out the environment variables and (possibly) program name - ! onto the stack. - mov si, di - dec si - std + ! Copy out the environment variables and (possibly) program name + ! onto the stack. + mov si, di + dec si + std copy_env: - and si, -2 - eseg lodsw - push ax - jnz copy_env - mov cx, sp + and si, -2 + eseg lodsw + push ax + jnz copy_env + mov cx, sp - ! Reset DF and es properly. - cld - push ss - pop es + ! Reset DF and es properly. + cld + push ss + pop es - ! Reserve space for argc and the argv and envp pointers on the - ! stack. These will be passed to __m_a_i_n later. - sub sp, 6 - mov ax, sp + ! Reserve space for argc and the argv and envp pointers on the + ! stack. These will be passed to __m_a_i_n later. + sub sp, 6 + mov ax, sp - ! Build up argc, argv[], and envp[]. - push ax ! output buffer for argc, argv, envp - push bp ! MS-DOS version - push cx ! env. string data - push dx ! count of env. vars. - mov ax, 0x0080 - push ax ! raw command line - call __sys_initmain - add sp, 10 + ! Build up argc, argv[], and envp[]. + push ax ! output buffer for argc, argv, envp + push bp ! MS-DOS version + push cx ! env. string data + push dx ! count of env. vars. + mov ax, 0x0080 + push ax ! raw command line + call __sys_initmain + add sp, 10 - ! Bail out if something went wrong. - test ax, ax - jnz no_room + ! Bail out if something went wrong. + test ax, ax + jnz no_room - ! argc, argv, and envp are now at the stack top. Now go. - call __m_a_i_n - add sp, 6 - push ax - call _exit + ! argc, argv, and envp are now at the stack top. Now go. + call __m_a_i_n + add sp, 6 + push ax + call _exit no_room: - mov dx, no_room_msg - call dos_msg - movb al, -1 - jmp al_exit + mov dx, no_room_msg + call dos_msg + movb al, -1 + jmp al_exit - ! Exit. + ! Exit. .define __exit .extern __exit .define EXIT .extern EXIT __exit: EXIT: - pop bx - pop ax + pop bx + pop ax al_exit: - movb ah, 0x4c - int 0x21 + movb ah, 0x4c + int 0x21 ! Define symbols at the beginning of our various segments, so that we can find ! them. (Except .text, which has already been done.) @@ -168,3 +290,6 @@ no_room_msg: .ascii 'No room$' .comm .trppc, 4 .comm .ignmask, 4 .comm _errno, 4 + +! vim: ts=4 sw=4 et ft=asm + From 21b30ccadb1d86258823f3f49bd67667658422bb Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 8 Aug 2022 23:22:00 +0200 Subject: [PATCH 07/20] We can now switch to 32-bit mode. --- plat/msdos386/boot.s | 67 +++++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/plat/msdos386/boot.s b/plat/msdos386/boot.s index de46f54e8..4c6d060cf 100644 --- a/plat/msdos386/boot.s +++ b/plat/msdos386/boot.s @@ -45,9 +45,8 @@ dpmi_cs = 0x2c dpmi_sp = 0x2e dpmi_ss = 0x30 -dpmi_ps = 0x32 ! WORD: protected register segment -dpmi_rs = 0x34 ! WORD: real register segment -dpmi_psp = 0x36 ! WORD: PSP segment +dpmi_rs = 0x32 ! WORD: real segment +dpmi_psp = 0x34 ! WORD: PSP segment dpmi_switch = 0x38 ! DWORD: far pointer of pmode switch routine .seek 0x3c @@ -79,33 +78,10 @@ exe_start: mov ax, 1 ! 32-bit app callf (dpmi_switch) - jc no_pmode + jnc pmode ! Success! - mov (dpmi_edx), go_msg - mov ax, (dpmi_rs) - mov (dpmi_ds), ax - mov (dpmi_eax+1), 9 - call int21 - mov ax, 0x4c00 - int 0x21 + ! Could not switch to protected mode. - ! Simulate DOS interrupt bx. -int21: - mov bx, 0x21 -callint: - xor ax, ax - mov (dpmi_ss), ax ! zero stack: DPMI host allocates one. - mov (dpmi_sp), ax - push ds - pop es - mov di, ax - mov ax, 0x300 - int 0x31 ! simulate DOS interrupt - push cs - pop ds - ret - -no_pmode: ! Could not switch to protected mode. mov dx, no_pmode_msg jmp exit_with_error @@ -120,8 +96,41 @@ exit_with_error: mov ax, 0x4cff int 0x21 ! terminate with error code al +pmode: + ! We're now in protected mode! Switch our code segment to 32-bit mode. + + mov cx, cs + lar cx, cx + movb cl, ch + movb ch, 0xc0 + mov bx, cs + mov ax, 0x0009 + int 0x31 ! Make selector 32 bit + .use32 -start_32bit: + o16 mov (dpmi_edx), go_msg + o16 mov ax, (dpmi_rs) + o16 mov (dpmi_ds), ax + movb (dpmi_eax+1), 9 + call int21 + o16 mov ax, 0x4c00 + int 0x21 + + ! Simulate DOS interrupt bx. +int21: + o16 mov bx, 0x21 +callint: + o16 xor ax, ax + o16 mov (dpmi_ss), ax ! zero stack: DPMI host allocates one. + o16 mov (dpmi_sp), ax + push ds + pop es + mov di, ax + o16 mov ax, 0x300 + int 0x31 ! simulate DOS interrupt + push cs + pop ds + ret go_msg: .ascii "Go!$" From b48b5b13ce4c4977008bb57d751459590e4263f0 Mon Sep 17 00:00:00 2001 From: David Given Date: Tue, 9 Aug 2022 23:32:41 +0200 Subject: [PATCH 08/20] Maybe have a working stub now. --- plat/msdos386/stub.s | 317 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 317 insertions(+) create mode 100644 plat/msdos386/stub.s diff --git a/plat/msdos386/stub.s b/plat/msdos386/stub.s new file mode 100644 index 000000000..7eb3b2ddc --- /dev/null +++ b/plat/msdos386/stub.s @@ -0,0 +1,317 @@ +# +! $Source$ +! $State$ +! $Revision$ + +! Declare segments (the order is important). + +.sect .text +.sect .rom +.sect .data +.sect .bss + +.sect .text +.use16 +exe_header: + .data2 0x5a4d ! magic number + .data2 exe_last_page ! number of bytes in last loadable page + .data2 exe_text_pages ! size of .exe, in pages + .data2 0 ! number of relocation entries + .data2 0 ! start of loadable area, in 16-byte paragraphs + .data2 exe_ram_paras ! required RAM size, in 16-byte paragraphs + .data2 exe_ram_paras ! maximum RAM siz, in 16-byte paragraphs + .data2 0 ! initial SS, relative to program + .data2 stack ! initial SP + .data2 0 ! checksum (ignored) + .data2 exe_start ! initial IP + .data2 0 ! initial CS, relative to program + .data2 0 ! offset of relocation table + .data2 0 ! overlay number + +exe_start: + ! On entry, DS=ES=PSP. Make DS=CS, so we're running in tiny mode. + + push cs + pop ds + mov (rseg), ds + mov (pspseg), es + + ! Ensure that at least two handles are available by blindly closing some. + + mov bx, 19 ! close handle + movb ah, 0x3e + int 0x21 + mov bx, 18 ! close handle + movb ah, 0x3e + int 0x21 + + ! Scan the environment to find the program name. + + eseg mov es, (0x2c) ! environment pointer segment from PSP + xor di, di + xorb al, al + mov cx, 0xffff +1: + repne scasb ! find end of next string + eseg cmpb (di), 0 + jnz 1b +2: + add di, 3 + mov si, di + repne scasb + + ! es:si now points at the program name, and es:di at one past the end. + + mov cx, di + sub cx, si + sub sp, cx ! allocate space on stack + mov di, sp ! es:si source, ds:di dest +1: + eseg movb al, (si) + inc si + movb (di), al + inc di + cmpb al, 0 + jnz 1b + + ! Open the file. (0x5f) + + mov dx, sp + mov ax, 0x3d00 + int 0x21 + jc no_file + mov (fh), ax + add sp, cx ! don't need filename any more + + ! Get the file length (== text len). + + mov bx, ax + mov ax, 0x4202 + xor cx, cx ! high offset + xor dx, dx ! low offset + int 0x21 ! lseek + mov (textlen+0), ax + mov (textlen+2), dx + + ! Initialise DPMI. + + mov ax, 0x1687 + int 0x2f + or ax, ax + jnz no_dpmi + mov (pmode_switch+0), di ! write back PMODE switch routine + mov (pmode_switch+2), es + or si, si ! do we need a DPMI private area? + jz 1f + + mov bx, si + movb ah, 0x48 + int 0x21 ! allocate memory from DOS + mov es, ax ! data area segment -> es +1: + ! Switch to protected mode. + + mov ax, 1 ! 32-bit app + callf (pmode_switch) + jc bad_dpmi + + ! We're now in protected mode. (0xa9) + + mov (psegcs), cs + mov (psegds), ds + + ! Allocate space for the code segment. + + mov ax, 0x0000 + mov cx, 1 + int 0x31 ! allocate LDT + jc bad_dpmi + mov es, ax + + mov cx, (textlen+0) + mov bx, (textlen+2) + mov ax, 0x0501 + int 0x31 ! allocate linear address + jc bad_dpmi + mov (pmemhandle+0), si + mov (pmemhandle+2), di + + mov dx, cx + mov cx, bx + mov bx, es + mov ax, 0x0007 + int 0x31 ! set segment base address + jc bad_dpmi + + mov bx, es + mov dx, (textlen+0) + mov cx, (textlen+2) + mov ax, 0x0008 + int 0x31 ! set segment limit + + mov cx, cs + and cx, 3 + shl cx, 5 + or cx, 0xc09b ! 32-bit, big, code, non-conforming, readable + mov bx, es + mov ax, 0x0009 + int 0x31 ! set descriptor access rights + + ! Load the program. (0xff) + + mov bx, (fh) + mov ax, 0x4200 + xor cx, cx ! high offset + xor dx, dx ! low offset + int 0x21 ! lseek + + o32 xor edi, edi ! destination 32-bit register +1: + movb ah, 0x3f + mov bx, (fh) + mov cx, TRANSFER_BUFFER_SIZE + mov dx, transfer_buffer + o32 push edi + call int21 ! read up to 32kB into transfer buffer + o32 pop edi + cmp ax, 0 + je 2f + + o32 movzx ecx, ax ! number of bytes read + o32 mov esi, transfer_buffer + o32 rep movsb + jmp 1b +2: + + ! Close the file. + + movb ah, 0x3e + mov bx, (fh) + int 0x21 ! close + + ! Jump to the new segment and enter 32-bit mode! + + o32 mov eax, (pmemhandle) + o32 movzx ebx, (rseg) + push es + push text_top + retf + +bad_dpmi: + mov si, bad_dpmi_msg + jmp exit_with_error + +no_file: + mov si, no_file_msg + jmp exit_with_error + +no_dpmi: + mov si, no_dpmi_msg + ! fall through + +! Displays the message in si and exits. +! This uses a loop because from protected mode any interrupt which +! takes a pointer parameter requires special treatment. +exit_with_error: + movb dl, (si) + cmpb dl, 0 + je 1f + inc si + + movb ah, 2 + int 0x21 ! print character + jmp exit_with_error +1: + mov ax, 0x4cff + int 0x21 ! terminate with error code al + +pmode: + .use32 + mov ax, 0x4c00 + int 0x21 + .use16 + + ! Simulate DOS interrupt. +int21: + mov (dpmi_eax), ax + mov (dpmi_ebx), bx + mov (dpmi_ecx), cx + mov (dpmi_edx), dx + mov ax, (rseg) + mov (dpmi_ds), ax + push es + push ds + xor ax, ax + mov (dpmi_ss), ax ! zero stack: DPMI host allocates one. + mov (dpmi_sp), ax + push ds + pop es + mov di, dpmi_edi + mov ax, 0x300 + mov bx, 0x21 + int 0x31 ! simulate DOS interrupt + pop ds + pop es + mov ax, (dpmi_eax) + mov bx, (dpmi_ebx) + mov cx, (dpmi_ecx) + mov dx, (dpmi_edx) + push (dpmi_flags) + popf + ret + +bad_dpmi_msg: + .asciz "DPMI error during setup" +no_file_msg: + .asciz "Couldn't open .exe" +no_dpmi_msg: + .asciz "No DPMI host installed" +text_top: + +exe_text_pages = [text_top - exe_header + 511] / 512 +exe_last_page = [text_top - exe_header] % 512 + +.sect .rom + +.sect .bss +bss_start: + +dpmi_edi: .space 4 +dpmi_esi: .space 4 +dpmi_ebp: .space 4 + .space 4 ! reserved +dpmi_ebx: .space 4 +dpmi_edx: .space 4 +dpmi_ecx: .space 4 +dpmi_eax: .space 4 +dpmi_flags: .space 2 +dpmi_es: .space 2 +dpmi_ds: .space 2 +dpmi_fs: .space 2 +dpmi_gs: .space 2 +dpmi_ip: .space 2 +dpmi_cs: .space 2 +dpmi_sp: .space 2 +dpmi_ss: .space 2 + +pmode_switch: .space 4 +rseg: .space 2 ! real mode +pspseg: .space 2 ! real mode +psegcs: .space 2 ! protected mode 16-bit code segment +psegds: .space 2 ! protected mode 16-bit data segment +pmemhandle: .space 4 ! protected mode linear memory handle +fh: .space 2 +textlen: .space 4 + + .space 128 +stack: + +TRANSFER_BUFFER_SIZE = 32*1024 +transfer_buffer: + .space TRANSFER_BUFFER_SIZE + +bss_top: +exe_ram_paras = [bss_top - bss_start + 15] / 16 + +! vim: ts=4 sw=4 et ft=asm + From d464606dd645a6d0ae904c499132ccccd0ab783f Mon Sep 17 00:00:00 2001 From: David Given Date: Tue, 9 Aug 2022 23:49:18 +0200 Subject: [PATCH 09/20] We can now load and run 32-bit protected-mode executables. We have not, however, set up the data segment. --- plat/msdos386/boot.s | 138 +----------------------------------- plat/msdos386/build-pkg.lua | 27 +++++++ plat/msdos386/descr | 2 +- plat/msdos386/stub.s | 11 +-- util/amisc/aslod.1 | 5 +- util/amisc/aslod.c | 22 ++++++ 6 files changed, 60 insertions(+), 145 deletions(-) diff --git a/plat/msdos386/boot.s b/plat/msdos386/boot.s index 4c6d060cf..81ab6a7ea 100644 --- a/plat/msdos386/boot.s +++ b/plat/msdos386/boot.s @@ -11,144 +11,12 @@ .sect .bss .sect .text -.use16 -exe_header: - .data2 0x5a4d ! magic number - .data2 0 ! number of bytes in last loadable page - .data2 exe_text_paras ! size of .exe, in pages - .data2 0 ! number of relocation entries - .data2 0 ! start of loadable area, in 16-byte paragraphs - .data2 exe_ram_paras ! required RAM size, in 16-byte paragraphs - .data2 0 ! maximum RAM siz, in 16-byte paragraphse - .data2 0 ! initial SS, relative to program - .data2 exe_stack ! initial SP - .data2 0 ! checksum (ignored) - .data2 exe_start ! initial IP - .data2 0 ! initial CS, relative to program - .data2 0 ! offset of relocation table - .data2 0 ! overlay number - -dpmi_edi = 0x00 -dpmi_esi = 0x04 -dpmi_ebp = 0x08 -dpmi_ebx = 0x10 -dpmi_edx = 0x14 -dpmi_ecx = 0x18 -dpmi_eax = 0x1c -dpmi_flags = 0x20 -dpmi_es = 0x22 -dpmi_ds = 0x24 -dpmi_fs = 0x26 -dpmi_gs = 0x28 -dpmi_ip = 0x2a -dpmi_cs = 0x2c -dpmi_sp = 0x2e -dpmi_ss = 0x30 - -dpmi_rs = 0x32 ! WORD: real segment -dpmi_psp = 0x34 ! WORD: PSP segment -dpmi_switch = 0x38 ! DWORD: far pointer of pmode switch routine - - .seek 0x3c -exe_start: - ! On entry, DS=ES=PSP. Make DS=CS, so we're running in tiny mode. - - push cs - pop ds - mov (dpmi_rs), ds - mov (dpmi_psp), es - - ! Initialise DPMI. - - mov ax, 0x1687 - int 0x2f - or ax, ax - jnz no_dpmi - mov (dpmi_switch+0), di ! write back PMODE switch routine - mov (dpmi_switch+2), es - or si, si ! do we need a DPMI private area? - jz 1f - - mov bx, si - movb ah, 0x48 - int 0x21 ! allocate memory from DOS - mov es, ax ! data area segment -> es -1: - ! Switch to protected mode. - - mov ax, 1 ! 32-bit app - callf (dpmi_switch) - jnc pmode ! Success! - - ! Could not switch to protected mode. - - mov dx, no_pmode_msg - jmp exit_with_error - -no_dpmi: - mov dx, no_dpmi_msg - ! fall through - -! Displays the message in dx and exits. -exit_with_error: - movb ah, 9 - int 0x21 ! print $-terminated string - mov ax, 0x4cff - int 0x21 ! terminate with error code al - -pmode: - ! We're now in protected mode! Switch our code segment to 32-bit mode. - - mov cx, cs - lar cx, cx - movb cl, ch - movb ch, 0xc0 - mov bx, cs - mov ax, 0x0009 - int 0x31 ! Make selector 32 bit - - .use32 - o16 mov (dpmi_edx), go_msg - o16 mov ax, (dpmi_rs) - o16 mov (dpmi_ds), ax - movb (dpmi_eax+1), 9 - call int21 - o16 mov ax, 0x4c00 - int 0x21 - - ! Simulate DOS interrupt bx. -int21: - o16 mov bx, 0x21 -callint: - o16 xor ax, ax - o16 mov (dpmi_ss), ax ! zero stack: DPMI host allocates one. - o16 mov (dpmi_sp), ax - push ds - pop es - mov di, ax - o16 mov ax, 0x300 - int 0x31 ! simulate DOS interrupt - push cs - pop ds - ret - -go_msg: - .ascii "Go!$" -no_pmode_msg: - .ascii "Couldn't switch to protected mode$" -no_dpmi_msg: - .ascii "No DPMI$" - -exe_top: - -exe_stack = exe_top + 512 -exe_text_paras = [exe_top - exe_header + 511] / 512 -exe_ram_paras = [exe_stack - exe_top + 15] / 16 - - #define STACK_BUFFER 128 /* number of bytes to leave for stack */ begtext: + mov eax, 0x4c00 + int 0x21 + ! Make sure we are running under MS-DOS 2 or above. ! ! While at it, also remember the actual DOS version, so that we know diff --git a/plat/msdos386/build-pkg.lua b/plat/msdos386/build-pkg.lua index 98cce47cc..4b92b5619 100644 --- a/plat/msdos386/build-pkg.lua +++ b/plat/msdos386/build-pkg.lua @@ -6,6 +6,32 @@ ackfile { vars = { plat = "msdos386" } } +ackfile { + name = "stub", + srcs = { "./stub.s" }, + vars = { plat = "msdos386" } +} + +normalrule { + name = "stub_aout", + ins = { + "util/led+led", + "+stub" + }, + outleaves = { "stub.aout" }, + commands = { "%{ins[1]} %{ins[2]} -o %{outs[1]}" } +} + +normalrule { + name = "stub_exe", + ins = { + "util/amisc+aslod", + "+stub_aout" + }, + outleaves = { "stub.exe" }, + commands = { "%{ins[1]} %{ins[2]} %{outs[1]}" } +} + build_plat_libs { name = "libs", arch = "i386", @@ -19,6 +45,7 @@ installable { "+libs", "./include+pkg", ["$(PLATIND)/msdos386/boot.o"] = "+boot", + ["$(PLATIND)/msdos386/stub.exe"] = "+stub_exe", ["$(PLATIND)/msdos386/libsys.a"] = "./libsys+lib", } } diff --git a/plat/msdos386/descr b/plat/msdos386/descr index f6559471e..a18c266e2 100644 --- a/plat/msdos386/descr +++ b/plat/msdos386/descr @@ -72,6 +72,6 @@ name cv from .out to .exe program {EM}/bin/aslod - args < > + args -p {PLATFORMDIR}/stub.exe < > outfile msdos386.exe end diff --git a/plat/msdos386/stub.s b/plat/msdos386/stub.s index 7eb3b2ddc..8422bcbf5 100644 --- a/plat/msdos386/stub.s +++ b/plat/msdos386/stub.s @@ -162,7 +162,7 @@ exe_start: mov bx, (fh) mov ax, 0x4200 xor cx, cx ! high offset - xor dx, dx ! low offset + mov dx, text_top ! low offset int 0x21 ! lseek o32 xor edi, edi ! destination 32-bit register @@ -194,7 +194,7 @@ exe_start: o32 mov eax, (pmemhandle) o32 movzx ebx, (rseg) push es - push text_top + push 0 retf bad_dpmi: @@ -225,12 +225,6 @@ exit_with_error: mov ax, 0x4cff int 0x21 ! terminate with error code al -pmode: - .use32 - mov ax, 0x4c00 - int 0x21 - .use16 - ! Simulate DOS interrupt. int21: mov (dpmi_eax), ax @@ -266,6 +260,7 @@ no_file_msg: .asciz "Couldn't open .exe" no_dpmi_msg: .asciz "No DPMI host installed" +.align 2 text_top: exe_text_pages = [text_top - exe_header + 511] / 512 diff --git a/util/amisc/aslod.1 b/util/amisc/aslod.1 index 5a1f857a0..a9f15ef3a 100644 --- a/util/amisc/aslod.1 +++ b/util/amisc/aslod.1 @@ -3,7 +3,7 @@ aslod \- ACK simple loader .SH SYNOPSIS .B aslod -[\-h] [\-v] inputfile outputfile +[\-h] [\-v] [\-p prefixfile] inputfile outputfile .SH DESCRIPTION .I aslod converts an absolute ack.out file into a simple binary memory dump. @@ -16,5 +16,8 @@ The file must have all references resolved and be linked to a fixed address. aslod will dump the segments, in order, such that the first byte of TEXT is at offset 0 in the file (regardless of where it is in memory). +.PP +If a prefix file is specified, this is prepended to the output before writing. +No changes to the output itself are made. .SH "SEE ALSO" ack.out(5) diff --git a/util/amisc/aslod.c b/util/amisc/aslod.c index 850c805f1..d5c3bee53 100644 --- a/util/amisc/aslod.c +++ b/util/amisc/aslod.c @@ -37,6 +37,7 @@ struct outsect outsect[S_MAX]; char* stringarea; char* outputfile = NULL; /* Name of output file, or NULL */ +char* prefixfile = NULL; /* Name of prefix file, or NULL */ char* program; /* Name of current program: argv[0] */ FILE* input; /* Input stream */ @@ -136,6 +137,19 @@ void emits(struct outsect* section, struct outsect* nextsect) } } +void emitprefixfile(void) +{ + FILE* fp = fopen(prefixfile, "rb"); + + while (!feof(fp)) + { + char buffer[BUFSIZ]; + size_t blocksize = fread(buffer, 1, BUFSIZ, fp); + writef(buffer, 1, blocksize); + } + + fclose(fp); +} /* Macros from modules/src/object/obj.h */ #define Xchar(ch) ((ch) & 0377) @@ -204,6 +218,12 @@ int main(int argc, char* argv[]) verbose = true; break; + case 'p': + argv++; + argc--; + prefixfile = argv[1]; + break; + default: syntaxerror: fatal("syntax error --- try -h for help"); @@ -288,6 +308,8 @@ int main(int argc, char* argv[]) /* And go! */ + if (prefixfile) + emitprefixfile(); emits(&outsect[TEXT], &outsect[ROM]); emits(&outsect[ROM], &outsect[DATA]); emits(&outsect[DATA], NULL); From b868c1ece95051372911b2d6e0d24738f6efc0cd Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 10 Aug 2022 00:15:28 +0200 Subject: [PATCH 10/20] Hacky workaround to make operatings on pointer differences work. --- mach/proto/as/comm7.c | 1 - 1 file changed, 1 deletion(-) diff --git a/mach/proto/as/comm7.c b/mach/proto/as/comm7.c index 969d0d84a..06e11042b 100644 --- a/mach/proto/as/comm7.c +++ b/mach/proto/as/comm7.c @@ -115,7 +115,6 @@ int combine(int typ1, int typ2, int op) return (S_ABS); break; } - fprintf(stderr, "typ1=%d typ2=%d pass=%d\n", typ1, typ2, pass); if (pass != PASS_1) serror("illegal operator"); return (S_UND); From 967b46e98e13e52b2354561043379a6df63d6a5b Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 10 Aug 2022 00:15:40 +0200 Subject: [PATCH 11/20] Hacky workaround to make lar work. --- mach/i386/as/mach5.c | 847 ++++++++++++++++++++++--------------------- 1 file changed, 425 insertions(+), 422 deletions(-) diff --git a/mach/i386/as/mach5.c b/mach/i386/as/mach5.c index 4c07402fb..8815828ec 100644 --- a/mach/i386/as/mach5.c +++ b/mach/i386/as/mach5.c @@ -10,8 +10,8 @@ void ea_1_16(int param) { - reg_1 &= 0377; - if ((reg_1 & 070) || (param & ~070)) { + reg_1 &= 0377; + if (param & ~070) { serror("bad operand"); } emit1(reg_1 | param); @@ -39,542 +39,545 @@ void ea_1_16(int param) } void ea_1(int param) { - if (! address_long) { - ea_1_16(param); - return; - } - if (is_expr(reg_1)) { - serror("bad operand"); - return; - } - if (is_reg(reg_1)) { - emit1(0300 | param | (reg_1&07)); - return; - } - if (rm_1 == 04) { - /* sib field use here */ - emit1(mod_1 << 6 | param | 04); - emit1(sib_1 | reg_1); - } - else emit1(mod_1<<6 | param | (reg_1&07)); - if ((mod_1 == 0 && reg_1 == 5) || mod_1 == 2) { - /* ??? should this be protected by a call to "small" ??? */ + if (! address_long) { + ea_1_16(param); + return; + } + if (is_expr(reg_1)) { + serror("bad operand"); + return; + } + if (is_reg(reg_1)) { + emit1(0300 | param | (reg_1&07)); + return; + } + if (rm_1 == 04) { + /* sib field use here */ + emit1(mod_1 << 6 | param | 04); + emit1(sib_1 | reg_1); + } + else emit1(mod_1<<6 | param | (reg_1&07)); + if ((mod_1 == 0 && reg_1 == 5) || mod_1 == 2) { + /* ??? should this be protected by a call to "small" ??? */ #ifdef RELOCATION - RELOMOVE(relonami, rel_1); - newrelo(exp_1.typ, RELO4); + RELOMOVE(relonami, rel_1); + newrelo(exp_1.typ, RELO4); #endif - emit4((long)(exp_1.val)); - } - else if (mod_1 == 1) { - emit1((int)(exp_1.val)); - } + emit4((long)(exp_1.val)); + } + else if (mod_1 == 1) { + emit1((int)(exp_1.val)); + } } void ea_2(int param) { - op_1 = op_2; - RELOMOVE(rel_1, rel_2); - ea_1(param); + op_1 = op_2; + RELOMOVE(rel_1, rel_2); + ea_1(param); } int checkscale(valu_t val) { - int v = val; + int v = val; - if (! address_long) { - serror("scaling not allowed in 16-bit mode"); - return 0; - } - if (v != val) v = 0; - switch(v) { - case 1: - return 0; - case 2: - return 1 << 6; - case 4: - return 2 << 6; - case 8: - return 3 << 6; - default: - serror("bad scale"); - return 0; - } - /*NOTREACHED*/ + if (! address_long) { + serror("scaling not allowed in 16-bit mode"); + return 0; + } + if (v != val) v = 0; + switch(v) { + case 1: + return 0; + case 2: + return 1 << 6; + case 4: + return 2 << 6; + case 8: + return 3 << 6; + default: + serror("bad scale"); + return 0; + } + /*NOTREACHED*/ } void reverse(void) { - struct operand op; + struct operand op; #ifdef RELOCATION - int r = rel_1; + int r = rel_1; - rel_1 = rel_2; rel_2 = r; + rel_1 = rel_2; rel_2 = r; #endif - op = op_1; op_1 = op_2; op_2 = op; + op = op_1; op_1 = op_2; op_2 = op; } void badsyntax(void) { - serror("bad operands"); + serror("bad operands"); } void regsize(int sz) { - register int bit; + register int bit; - bit = (sz&1) ? 0 : IS_R8; - if ((is_reg(reg_1) && (reg_1 & IS_R8) != bit) || - (is_reg(reg_2) && (reg_2 & IS_R8) != bit)) - serror("register error"); - if (! address_long) { - reg_1 &= ~010; - reg_2 &= ~010; - } + bit = (sz&1) ? 0 : IS_R8; + if ((is_reg(reg_1) && (reg_1 & IS_R8) != bit) || + (is_reg(reg_2) && (reg_2 & IS_R8) != bit)) + serror("register error"); + if (! address_long) { + reg_1 &= ~010; + reg_2 &= ~010; + } } void indexed(void) { - if (address_long) { - mod_2 = 0; - if (sib_2 == -1) - serror("register error"); - if (rm_2 == 0 && reg_2 == 4) { - /* base register sp, no index register; use - indexed mode without index register - */ - rm_2 = 04; - sib_2 = 044; - } - if (reg_2 == 015) { - reg_2 = 05; - return; - } - if (small(exp_2.typ == S_ABS && fitb(exp_2.val), 3)) { - if (small(exp_2.val == 0 && reg_2 != 5, 1)) { - } - else mod_2 = 01; - } - else if (small(0, 1)) { - } - else mod_2 = 02; - } - else { - if (reg_2 & ~7) - serror("register error"); - if (small(exp_2.typ == S_ABS && fitb(exp_2.val), 1)) { - if (small(exp_2.val == 0 && reg_2 != 6, 1)) { - } - else reg_2 |= 0100; - } - else if (small(0, 1)) { - } - else reg_2 |= 0200; - } + if (address_long) { + mod_2 = 0; + if (sib_2 == -1) + serror("register error"); + if (rm_2 == 0 && reg_2 == 4) { + /* base register sp, no index register; use + indexed mode without index register + */ + rm_2 = 04; + sib_2 = 044; + } + if (reg_2 == 015) { + reg_2 = 05; + return; + } + if (small(exp_2.typ == S_ABS && fitb(exp_2.val), 3)) { + if (small(exp_2.val == 0 && reg_2 != 5, 1)) { + } + else mod_2 = 01; + } + else if (small(0, 1)) { + } + else mod_2 = 02; + } + else { + if (reg_2 & ~7) + serror("register error"); + if (small(exp_2.typ == S_ABS && fitb(exp_2.val), 1)) { + if (small(exp_2.val == 0 && reg_2 != 6, 1)) { + } + else reg_2 |= 0100; + } + else if (small(0, 1)) { + } + else reg_2 |= 0200; + } } void ebranch(register int opc,expr_t exp) { - /* Conditional branching; Full displacements are available - on the 80386, so the welknown trick with the reverse branch - over a jump is not needed here. - The only complication here is with the address size, which - can be set with a prefix. In this case, the user gets what - he asked for. - */ - register int sm; - register long dist; - int saving = address_long ? 4 : 2; + /* Conditional branching; Full displacements are available + on the 80386, so the welknown trick with the reverse branch + over a jump is not needed here. + The only complication here is with the address size, which + can be set with a prefix. In this case, the user gets what + he asked for. + */ + register int sm; + register long dist; + int saving = address_long ? 4 : 2; - if (opc == 0353) saving--; - dist = exp.val - (DOTVAL + 2); - if (pass == PASS_2 && dist > 0 && !(exp.typ & S_DOT)) - dist -= DOTGAIN; - sm = dist > 0 ? fitb(dist-saving) : fitb(dist); - if ((exp.typ & ~S_DOT) != DOTTYP) - sm = 0; - if ((sm = small(sm,saving)) == 0) { - if (opc == 0353) { - emit1(0xe9); - } - else { - emit1(0xF); - emit1(opc | 0x80); - } - dist -= saving; - exp.val = dist; - adsize_exp(exp, RELPC); - } - else { - if (opc == 0353) { - emit1(opc); - } - else { - emit1(opc | 0x70); - } - emit1((int)dist); - } + if (opc == 0353) saving--; + dist = exp.val - (DOTVAL + 2); + if (pass == PASS_2 && dist > 0 && !(exp.typ & S_DOT)) + dist -= DOTGAIN; + sm = dist > 0 ? fitb(dist-saving) : fitb(dist); + if ((exp.typ & ~S_DOT) != DOTTYP) + sm = 0; + if ((sm = small(sm,saving)) == 0) { + if (opc == 0353) { + emit1(0xe9); + } + else { + emit1(0xF); + emit1(opc | 0x80); + } + dist -= saving; + exp.val = dist; + adsize_exp(exp, RELPC); + } + else { + if (opc == 0353) { + emit1(opc); + } + else { + emit1(opc | 0x70); + } + emit1((int)dist); + } } void branch(register int opc,expr_t exp) { - /* LOOP, JCXZ, etc. branch instructions. - Here, the offset just must fit in a byte. - */ - register long dist; + /* LOOP, JCXZ, etc. branch instructions. + Here, the offset just must fit in a byte. + */ + register long dist; - dist = exp.val - (DOTVAL + 2); - if (pass == PASS_2 && dist > 0 && !(exp.typ & S_DOT)) - dist -= DOTGAIN; - fit((exp.typ & ~S_DOT) == DOTTYP && fitb(dist)); - emit1(opc); - emit1((int)dist); + dist = exp.val - (DOTVAL + 2); + if (pass == PASS_2 && dist > 0 && !(exp.typ & S_DOT)) + dist -= DOTGAIN; + fit((exp.typ & ~S_DOT) == DOTTYP && fitb(dist)); + emit1(opc); + emit1((int)dist); } void pushop(register int opc) { - regsize(1); - if (is_segreg(reg_1)) { - /* segment register */ - if ((reg_1 & 07) <= 3) - emit1(6 | opc | (reg_1&7)<<3); - else { - emit1(0xF); - emit1(0200 | opc | ((reg_1&7)<<3)); - } - } else if (is_reg(reg_1)) { - /* normal register */ - emit1(0120 | opc<<3 | (reg_1&7)); - } else if (opc == 0) { - if (is_expr(reg_1)) { - if (small(exp_1.typ == S_ABS && fitb(exp_1.val), - operand_long ? 3 : 1)) { - emit1(0152); - emit1((int)(exp_1.val)); - } - else { - emit1(0150); - RELOMOVE(relonami, rel_1); - opsize_exp(exp_1, 1); - } - } - else { - emit1(0377); ea_1(6<<3); - } - } else { - emit1(0217); ea_1(0<<3); - } + regsize(1); + if (is_segreg(reg_1)) { + /* segment register */ + if ((reg_1 & 07) <= 3) + emit1(6 | opc | (reg_1&7)<<3); + else { + emit1(0xF); + emit1(0200 | opc | ((reg_1&7)<<3)); + } + } else if (is_reg(reg_1)) { + /* normal register */ + emit1(0120 | opc<<3 | (reg_1&7)); + } else if (opc == 0) { + if (is_expr(reg_1)) { + if (small(exp_1.typ == S_ABS && fitb(exp_1.val), + operand_long ? 3 : 1)) { + emit1(0152); + emit1((int)(exp_1.val)); + } + else { + emit1(0150); + RELOMOVE(relonami, rel_1); + opsize_exp(exp_1, 1); + } + } + else { + emit1(0377); ea_1(6<<3); + } + } else { + emit1(0217); ea_1(0<<3); + } } void opsize_exp(expr_t exp, int nobyte) { - if (! nobyte) { + if (! nobyte) { #ifdef RELOCATION - newrelo(exp.typ, RELO1); + newrelo(exp.typ, RELO1); #endif - emit1((int)(exp.val)); - } - else if (operand_long) { + emit1((int)(exp.val)); + } + else if (operand_long) { #ifdef RELOCATION - newrelo(exp.typ, RELO4); + newrelo(exp.typ, RELO4); #endif - emit4((long)(exp.val)); - } - else { + emit4((long)(exp.val)); + } + else { #ifdef RELOCATION - newrelo(exp.typ, RELO2); + newrelo(exp.typ, RELO2); #endif - emit2((int)(exp.val)); - } + emit2((int)(exp.val)); + } } void adsize_exp(expr_t exp, int relpc) { - if (address_long) { + if (address_long) { #ifdef RELOCATION - newrelo(exp.typ, RELO4 | relpc); + newrelo(exp.typ, RELO4 | relpc); #endif - emit4((long)(exp.val)); - } - else { + emit4((long)(exp.val)); + } + else { #ifdef RELOCATION - newrelo(exp.typ, RELO2 | relpc); + newrelo(exp.typ, RELO2 | relpc); #endif - emit2((int)(exp.val)); - } + emit2((int)(exp.val)); + } } void addop(register int opc) { - regsize(opc); - if (is_reg(reg_2)) { - /* Add register to register or memory */ - emit1(opc); ea_1((reg_2&7)<<3); - } else if (is_acc(reg_1) && is_expr(reg_2)) { - /* Add immediate to accumulator */ - emit1(opc | 4); - RELOMOVE(relonami, rel_2); - opsize_exp(exp_2, (opc&1)); - } else if (is_expr(reg_2)) { - /* Add immediate to register or memory */ - if ((opc&1) == 0) { - emit1(0200); - } else if (! small(exp_2.typ == S_ABS && fitb(exp_2.val), - operand_long ? 3 : 1)) { - emit1(0201); - } else { - emit1(0203); opc &= ~1; - } - ea_1(opc & 070); - RELOMOVE(relonami, rel_2); - opsize_exp(exp_2, (opc&1)); - } else if (is_reg(reg_1)) { - /* Add register or memory to register */ - emit1(opc | 2); - ea_2((reg_1&7)<<3); - } else - badsyntax(); + regsize(opc); + if (is_reg(reg_2)) { + /* Add register to register or memory */ + emit1(opc); ea_1((reg_2&7)<<3); + } else if (is_acc(reg_1) && is_expr(reg_2)) { + /* Add immediate to accumulator */ + emit1(opc | 4); + RELOMOVE(relonami, rel_2); + opsize_exp(exp_2, (opc&1)); + } else if (is_expr(reg_2)) { + /* Add immediate to register or memory */ + if ((opc&1) == 0) { + emit1(0200); + } else if (! small(exp_2.typ == S_ABS && fitb(exp_2.val), + operand_long ? 3 : 1)) { + emit1(0201); + } else { + emit1(0203); opc &= ~1; + } + ea_1(opc & 070); + RELOMOVE(relonami, rel_2); + opsize_exp(exp_2, (opc&1)); + } else if (is_reg(reg_1)) { + /* Add register or memory to register */ + emit1(opc | 2); + ea_2((reg_1&7)<<3); + } else + badsyntax(); } void rolop(register int opc) { - register int oreg; + register int oreg; - oreg = reg_2; - reg_2 = reg_1; - regsize(opc); - if (oreg == (IS_R8 | 1 | (address_long ? 0 : 0300))) { - /* cl register */ - emit1(0322 | (opc&1)); ea_1(opc&070); - } else if (is_expr(oreg)) { - if (small(exp_2.typ == S_ABS && exp_2.val == 1, 1)) { - /* shift by 1 */ - emit1(0320 | (opc&1)); ea_1(opc&070); - } else { - /* shift by byte count */ - emit1(0300 | (opc & 1)); - ea_1(opc & 070); + oreg = reg_2; + reg_2 = reg_1; + regsize(opc); + if (oreg == (IS_R8 | 1 | (address_long ? 0 : 0300))) { + /* cl register */ + emit1(0322 | (opc&1)); ea_1(opc&070); + } else if (is_expr(oreg)) { + if (small(exp_2.typ == S_ABS && exp_2.val == 1, 1)) { + /* shift by 1 */ + emit1(0320 | (opc&1)); ea_1(opc&070); + } else { + /* shift by byte count */ + emit1(0300 | (opc & 1)); + ea_1(opc & 070); #ifdef RELOCATION - RELOMOVE(relonami, rel_2); - newrelo(exp_2.typ, RELO1); + RELOMOVE(relonami, rel_2); + newrelo(exp_2.typ, RELO1); #endif - emit1((int)(exp_2.val)); - } - } - else - badsyntax(); + emit1((int)(exp_2.val)); + } + } + else + badsyntax(); } void incop(register int opc) { - regsize(opc); - if ((opc&1) && is_reg(reg_1)) { - /* word register */ - emit1(0100 | (opc&010) | (reg_1&7)); - } else { - emit1(0376 | (opc&1)); - ea_1(opc & 010); - } + regsize(opc); + if ((opc&1) && is_reg(reg_1)) { + /* word register */ + emit1(0100 | (opc&010) | (reg_1&7)); + } else { + emit1(0376 | (opc&1)); + ea_1(opc & 010); + } } void callop(register int opc) { - regsize(1); - if (is_expr(reg_1)) { - if (opc == (040+(0351<<8))) { - RELOMOVE(relonami, rel_1); - ebranch(0353,exp_1); - } else { - exp_1.val -= (DOTVAL+3 + (address_long ? 2 : 0)); - emit1(opc>>8); - RELOMOVE(relonami, rel_1); - adsize_exp(exp_1, RELPC); - } - } else { - emit1(0377); ea_1(opc&070); - } + regsize(1); + if (is_expr(reg_1)) { + if (opc == (040+(0351<<8))) { + RELOMOVE(relonami, rel_1); + ebranch(0353,exp_1); + } else { + exp_1.val -= (DOTVAL+3 + (address_long ? 2 : 0)); + emit1(opc>>8); + RELOMOVE(relonami, rel_1); + adsize_exp(exp_1, RELPC); + } + } else { + emit1(0377); ea_1(opc&070); + } } void xchg(register int opc) { - regsize(opc); - if (! is_reg(reg_1) || is_acc(reg_2)) { - reverse(); - } - if (opc == 1 && is_acc(reg_1) && is_reg(reg_2)) { - emit1(0220 | (reg_2&7)); - } else if (is_reg(reg_1)) { - emit1(0206 | opc); ea_2((reg_1&7)<<3); - } else - badsyntax(); + regsize(opc); + if (! is_reg(reg_1) || is_acc(reg_2)) { + reverse(); + } + if (opc == 1 && is_acc(reg_1) && is_reg(reg_2)) { + emit1(0220 | (reg_2&7)); + } else if (is_reg(reg_1)) { + emit1(0206 | opc); ea_2((reg_1&7)<<3); + } else + badsyntax(); } void test(register int opc) { - regsize(opc); - if (is_reg(reg_2) || is_expr(reg_1)) - reverse(); - if (is_expr(reg_2)) { - if (is_acc(reg_1)) { - emit1(0250 | opc); - RELOMOVE(relonami, rel_2); - opsize_exp(exp_2, (opc&1)); - } - else { - emit1(0366 | opc); - ea_1(0<<3); - RELOMOVE(relonami, rel_2); - opsize_exp(exp_2, (opc&1)); - } - } else if (is_reg(reg_1)) { - emit1(0204 | opc); ea_2((reg_1&7)<<3); - } else - badsyntax(); + regsize(opc); + if (is_reg(reg_2) || is_expr(reg_1)) + reverse(); + if (is_expr(reg_2)) { + if (is_acc(reg_1)) { + emit1(0250 | opc); + RELOMOVE(relonami, rel_2); + opsize_exp(exp_2, (opc&1)); + } + else { + emit1(0366 | opc); + ea_1(0<<3); + RELOMOVE(relonami, rel_2); + opsize_exp(exp_2, (opc&1)); + } + } else if (is_reg(reg_1)) { + emit1(0204 | opc); ea_2((reg_1&7)<<3); + } else + badsyntax(); } void mov(register int opc) { - regsize(opc); - if (is_segreg(reg_1)) { - /* to segment register */ - emit1(0216); ea_2((reg_1&07)<<3); - } else if (is_segreg(reg_2)) { - /* from segment register */ - emit1(0214); ea_1((reg_2&07)<<3); - } else if (is_expr(reg_2)) { - /* from immediate */ - if (is_reg(reg_1)) { - /* to register */ - emit1(0260 | opc<<3 | (reg_1&7)); - } else { - /* to memory */ - emit1(0306 | opc); ea_1(0<<3); - } - RELOMOVE(relonami, rel_2); - opsize_exp(exp_2, (opc&1)); - } else if (rm_1 == 05 && is_acc(reg_2)) { - /* from accumulator to memory (displacement) */ - emit1(0242 | opc); - RELOMOVE(relonami, rel_1); - adsize_exp(exp_1, 0); - } else if (rm_2 == 05 && is_acc(reg_1)) { - /* from memory (displacement) to accumulator */ - emit1(0240 | opc); - RELOMOVE(relonami, rel_2); - adsize_exp(exp_2, 0); - } else if (is_reg(reg_2)) { - /* from register to memory or register */ - emit1(0210 | opc); ea_1((reg_2&07)<<3); - } else if (is_reg(reg_1)) { - /* from memory or register to register */ - emit1(0212 | opc); ea_2((reg_1&07)<<3); - } else - badsyntax(); + regsize(opc); + if (is_segreg(reg_1)) { + /* to segment register */ + emit1(0216); ea_2((reg_1&07)<<3); + } else if (is_segreg(reg_2)) { + /* from segment register */ + emit1(0214); ea_1((reg_2&07)<<3); + } else if (is_expr(reg_2)) { + /* from immediate */ + if (is_reg(reg_1)) { + /* to register */ + emit1(0260 | opc<<3 | (reg_1&7)); + } else { + /* to memory */ + emit1(0306 | opc); ea_1(0<<3); + } + RELOMOVE(relonami, rel_2); + opsize_exp(exp_2, (opc&1)); + } else if (rm_1 == 05 && is_acc(reg_2)) { + /* from accumulator to memory (displacement) */ + emit1(0242 | opc); + RELOMOVE(relonami, rel_1); + adsize_exp(exp_1, 0); + } else if (rm_2 == 05 && is_acc(reg_1)) { + /* from memory (displacement) to accumulator */ + emit1(0240 | opc); + RELOMOVE(relonami, rel_2); + adsize_exp(exp_2, 0); + } else if (is_reg(reg_2)) { + /* from register to memory or register */ + emit1(0210 | opc); ea_1((reg_2&07)<<3); + } else if (is_reg(reg_1)) { + /* from memory or register to register */ + emit1(0212 | opc); ea_2((reg_1&07)<<3); + } else + badsyntax(); } void extshft(int opc, int reg) { - int oreg2 = reg_2; + int oreg2 = reg_2; - reg_2 = reg_1; - regsize(1); + reg_2 = reg_1; + regsize(1); - emit1(0xF); - if (oreg2 == (IS_R8 | 1 | (address_long ? 0 : 0300))) { - /* cl register */ - emit1(opc|1); - ea_1(reg << 3); - } - else if (is_expr(oreg2)) { - emit1(opc); - ea_1(reg << 3); + emit1(0xF); + if (oreg2 == (IS_R8 | 1 | (address_long ? 0 : 0300))) { + /* cl register */ + emit1(opc|1); + ea_1(reg << 3); + } + else if (is_expr(oreg2)) { + emit1(opc); + ea_1(reg << 3); #ifdef RELOCATION - RELOMOVE(relonami, rel_2); - newrelo(exp_2.typ, RELO1); + RELOMOVE(relonami, rel_2); + newrelo(exp_2.typ, RELO1); #endif - emit1((int)(exp_2.val)); - } - else badsyntax(); + emit1((int)(exp_2.val)); + } + else badsyntax(); } void bittestop(int opc) { - regsize(1); - emit1(0xF); - if (is_expr(reg_2)) { - emit1(0272); - ea_1(opc << 3); + regsize(1); + emit1(0xF); + if (is_expr(reg_2)) { + emit1(0272); + ea_1(opc << 3); #ifdef RELOCATION - RELOMOVE(relonami, rel_2); - newrelo(exp_2.typ, RELO1); + RELOMOVE(relonami, rel_2); + newrelo(exp_2.typ, RELO1); #endif - emit1((int)(exp_2.val)); - } - else if (is_reg(reg_2)) { - emit1(0203 | (opc<<3)); - ea_1((reg_2&7)<<3); - } - else badsyntax(); + emit1((int)(exp_2.val)); + } + else if (is_reg(reg_2)) { + emit1(0203 | (opc<<3)); + ea_1((reg_2&7)<<3); + } + else badsyntax(); } void imul(int reg) { - /* This instruction is more elaborate on the 80386. Its most - general form is: - imul reg, reg_or_mem, immediate. - This is the form processed here. - */ - regsize(1); - if (is_expr(reg_1)) { - /* To also handle - imul reg, immediate, reg_or_mem - */ - reverse(); - } - if (is_expr(reg_2)) { - /* The immediate form; two cases: */ - if (small(exp_2.typ == S_ABS && fitb(exp_2.val), - operand_long ? 3 : 1)) { - /* case 1: 1 byte encoding of immediate */ - emit1(0153); - ea_1((reg & 07) << 3); - emit1((int)(exp_2.val)); - } - else { - /* case 2: WORD or DWORD encoding of immediate */ - emit1(0151); - ea_1((reg & 07) << 3); - RELOMOVE(relonami, rel_2); - opsize_exp(exp_2, 1); - } - } - else if (is_reg(reg_1) && ((reg_1&7) == (reg & 07))) { - /* the "reg" field and the "reg_or_mem" field are the same, - and the 3rd operand is not an immediate ... - */ - if (reg == 0) { - /* how lucky we are, the target is the ax register */ - /* However, we cannot make an optimization for f.i. - imul eax, blablabla - because the latter does not affect edx, whereas - imul blablabla - does! Therefore, "reg" is or-ed with 0x10 in the - former case, so that the test above fails. - */ - emit1(0367); - ea_2(050); - } - else { - /* another register ... */ - emit1(0xF); - emit1(0257); - ea_2((reg & 07) << 3); - } - } - else badsyntax(); + /* This instruction is more elaborate on the 80386. Its most + general form is: + imul reg, reg_or_mem, immediate. + This is the form processed here. + */ + regsize(1); + if (is_expr(reg_1)) { + /* To also handle + imul reg, immediate, reg_or_mem + */ + reverse(); + } + if (is_expr(reg_2)) { + /* The immediate form; two cases: */ + if (small(exp_2.typ == S_ABS && fitb(exp_2.val), + operand_long ? 3 : 1)) { + /* case 1: 1 byte encoding of immediate */ + emit1(0153); + ea_1((reg & 07) << 3); + emit1((int)(exp_2.val)); + } + else { + /* case 2: WORD or DWORD encoding of immediate */ + emit1(0151); + ea_1((reg & 07) << 3); + RELOMOVE(relonami, rel_2); + opsize_exp(exp_2, 1); + } + } + else if (is_reg(reg_1) && ((reg_1&7) == (reg & 07))) { + /* the "reg" field and the "reg_or_mem" field are the same, + and the 3rd operand is not an immediate ... + */ + if (reg == 0) { + /* how lucky we are, the target is the ax register */ + /* However, we cannot make an optimization for f.i. + imul eax, blablabla + because the latter does not affect edx, whereas + imul blablabla + does! Therefore, "reg" is or-ed with 0x10 in the + former case, so that the test above fails. + */ + emit1(0367); + ea_2(050); + } + else { + /* another register ... */ + emit1(0xF); + emit1(0257); + ea_2((reg & 07) << 3); + } + } + else badsyntax(); } + +// vim: ts=8 sw=8 et + From 1764c6baa285b9b5c6afbce24b38ac988fdbe255 Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 10 Aug 2022 16:14:12 +0200 Subject: [PATCH 12/20] Made realloc work; the 32-bit process can now be resized to include bss and stack. --- plat/msdos386/boot.s | 114 ++++++++++++++++++++++++++---------------- plat/msdos386/descr | 2 + plat/msdos386/stub.s | 115 +++++++++++++++++++++++++++++++++++++------ 3 files changed, 172 insertions(+), 59 deletions(-) diff --git a/plat/msdos386/boot.s b/plat/msdos386/boot.s index 81ab6a7ea..858785558 100644 --- a/plat/msdos386/boot.s +++ b/plat/msdos386/boot.s @@ -13,57 +13,73 @@ .sect .text #define STACK_BUFFER 128 /* number of bytes to leave for stack */ +! g 18b to break at the retf before coming here begtext: - mov eax, 0x4c00 - int 0x21 - - ! Make sure we are running under MS-DOS 2 or above. + ! On entry, the stub has cs and ds pointing at the 32-bit + ! segment, but ss is still pointing at the 16-bit segment. ! - ! While at it, also remember the actual DOS version, so that we know - ! whether DOS gives us the program's name in the environment - ! segment. (DOS 3+ does; DOS 2.x does not.) - movb ah, 0x30 - int 0x21 - cbw - cmpb al, 2 - xchg bp, ax - jnc ok_sys + ! si:di memory handle of linear block + ! ax: pmode code segment of stub + ! dx: pointer to realloc routine + ! fs: data segment (just a clone of the code segment) - mov dx, bad_sys_msg -dos_msg: - ret + ! Resize the segment to include the BSS. -ok_sys: - ! Resize the program's memory control block (MCB) to cover only the - ! program's near code and data space. Use the starting sp value as - ! a guide to how much memory we can grab. Abort on any failure. - ! - ! As a side effect, this also frees up any memory allocated to our - ! program beyond 64 KiB. (The freed memory can possibly be used by - ! e.g. child processes, in the future.) - ! - ! Also check that we have some space between the BSS end and the - ! starting sp. - cmp sp, endbss+STACK_BUFFER - jb no_room - - movb ah, 0x4a - mov bx, sp - movb cl, 4 - shr bx, cl - inc bx - int 0x21 - jc no_room + o16 cseg mov (realloc_ptr+4), ax + cseg mov (realloc_ptr+0), edx + mov eax, endbss + cseg callf (realloc_ptr) ! Clear BSS. - mov di, begbss - mov cx, endbss+1 - sub cx, di - shr cx, 1 - xor ax, ax + + mov edi, begbss + mov ecx, endbss+1 + sub ecx, edi + shr ecx, 1 + xor eax, eax cld rep stosw + ! It's now safe to switch stacks. + + cli + mov eax, ds + mov ss, eax + mov sp, .stack + sti + + ! Create a handle for low 1MB access. + + o16 mov ax, 0x0000 + o16 mov cx, 1 + int 0x31 ! allocate LDT + mov es, ax + o16 mov bx, ax + o16 mov (.doshandle), bx + + xor ecx, ecx + xor edx, edx + o16 mov ax, 0x0007 + int 0x31 ! set base address to 0 + o16 mov cx, 0x0010 + o16 mov ax, 0x0008 + int 0x31 ! set limit to 1MB + + mov cx, ds + and cx, 3 + shl cx, 5 + or cx, 0xc093 ! 32-bit, big, data, r/w, expand-up + mov ax, 0x0009 + int 0x31 ! set descriptor access rights + + ! Locate the PSP. + + movb ah, 0x62 + int 0x21 + movzx ebx, bx + shl ebx, 4 ! convert to linear address + mov (.psp), ebx + ! Get the size of the environment variables plus (if present) the ! program name. Also count the number of environment variables. xor di, di @@ -130,7 +146,7 @@ copy_env: no_room: mov dx, no_room_msg - call dos_msg + !call dos_msg movb al, -1 jmp al_exit @@ -147,6 +163,11 @@ al_exit: movb ah, 0x4c int 0x21 + ! This must be in the code segment due to bootstrap issues. +realloc_ptr: + .data2 0 + .data4 0 + ! Define symbols at the beginning of our various segments, so that we can find ! them. (Except .text, which has already been done.) @@ -168,5 +189,12 @@ no_room_msg: .ascii 'No room$' .comm .ignmask, 4 .comm _errno, 4 +.comm .doshandle, 2 +.comm .psp, 4 + +.sect .bss + .space 512 +.stack: + ! vim: ts=4 sw=4 et ft=asm diff --git a/plat/msdos386/descr b/plat/msdos386/descr index a18c266e2..718424e21 100644 --- a/plat/msdos386/descr +++ b/plat/msdos386/descr @@ -39,6 +39,7 @@ name as program {EM}/lib/ack/{PLATFORM}/as args - -o > < prep cond + end name led from .o.a @@ -66,6 +67,7 @@ name led {PLATFORMDIR}/libc.a \ {PLATFORMDIR}/libem.a \ {PLATFORMDIR}/libend.a) + linker end name cv diff --git a/plat/msdos386/stub.s b/plat/msdos386/stub.s index 8422bcbf5..863d5d8f7 100644 --- a/plat/msdos386/stub.s +++ b/plat/msdos386/stub.s @@ -51,6 +51,7 @@ exe_start: xor di, di xorb al, al mov cx, 0xffff + cld 1: repne scasb ! find end of next string eseg cmpb (di), 0 @@ -90,8 +91,8 @@ exe_start: xor cx, cx ! high offset xor dx, dx ! low offset int 0x21 ! lseek - mov (textlen+0), ax - mov (textlen+2), dx + mov (pmemlen+0), ax + mov (pmemlen+2), dx ! Initialise DPMI. @@ -115,7 +116,7 @@ exe_start: callf (pmode_switch) jc bad_dpmi - ! We're now in protected mode. (0xa9) + ! We're now in protected mode. (ae) mov (psegcs), cs mov (psegds), ds @@ -127,14 +128,15 @@ exe_start: int 0x31 ! allocate LDT jc bad_dpmi mov es, ax + mov (psegcs32), ax - mov cx, (textlen+0) - mov bx, (textlen+2) + mov cx, (pmemlen+0) + mov bx, (pmemlen+2) mov ax, 0x0501 int 0x31 ! allocate linear address jc bad_dpmi - mov (pmemhandle+0), si - mov (pmemhandle+2), di + mov (pmemhandle+0), di + mov (pmemhandle+2), si mov dx, cx mov cx, bx @@ -144,8 +146,8 @@ exe_start: jc bad_dpmi mov bx, es - mov dx, (textlen+0) - mov cx, (textlen+2) + mov dx, (pmemlen+0) + mov cx, (pmemlen+2) mov ax, 0x0008 int 0x31 ! set segment limit @@ -157,7 +159,23 @@ exe_start: mov ax, 0x0009 int 0x31 ! set descriptor access rights - ! Load the program. (0xff) + ! Allocate the data segment (as a simple clone of the code segment). (10e) + + mov ax, 0x000a + mov bx, es + int 0x31 + mov fs, ax + mov (psegds32), ax + + mov cx, ax + and cx, 3 + shl cx, 5 + or cx, 0xc093 ! 32-bit, big, data, r/w, expand-up + mov bx, fs + mov ax, 0x0009 + int 0x31 ! set descriptor access rights + + ! Load the program. mov bx, (fh) mov ax, 0x4200 @@ -179,6 +197,7 @@ exe_start: o32 movzx ecx, ax ! number of bytes read o32 mov esi, transfer_buffer + cld o32 rep movsb jmp 1b 2: @@ -191,12 +210,75 @@ exe_start: ! Jump to the new segment and enter 32-bit mode! - o32 mov eax, (pmemhandle) - o32 movzx ebx, (rseg) + mov ax, (psegcs) + mov bx, (psegds) + mov cx, (rseg) + o32 mov edx, realloc + push es + pop ds push es push 0 retf + ! ALL CODE ABOVE THIS POINT DISCARDED ON ENTRY TO 32-BIT CODE + ! (it's reused as the 16-bit stack) +stack16: + + ! Helper routine which reallocates the linear block that the 32-bit code + ! is running from. This can't happen from inside the 32-bit code itself + ! because it might move. + ! + ! On entry, ds and ss are ignored. On exit, ds is set to the 32-bit segment. + ! eax: new block size +realloc: + cseg mov ds, (psegds) + cli ! atomically switch stacks + o32 mov (dpmi_ebp), esp ! yes, saving esp into the ebp field + mov (dpmi_ss), ss + mov ss, (psegds) + mov sp, stack16 + sti + pusha + + o32 add eax, 1024*1024 - 1 + o32 and eax, ~[1024*1024 - 1] + o32 mov (pmemlen), eax + mov cx, (pmemlen+0) + mov bx, (pmemlen+2) + mov di, (pmemhandle+0) + mov si, (pmemhandle+2) + mov ax, 0x0503 + int 0x31 ! resize memory block + jc bad_dpmi + mov (pmemhandle+0), di + mov (pmemhandle+2), si + mov (pmemaddr+0), cx + mov (pmemaddr+2), bx + + mov bx, (psegds32) + mov dx, (pmemlen+0) + mov cx, (pmemlen+2) + mov ax, 0x0008 + int 0x31 ! set ds segment limit + jc bad_dpmi + mov dx, (pmemaddr+0) + mov cx, (pmemaddr+2) + mov ax, 0x0007 + int 0x31 ! set ds linear address + jc bad_dpmi + mov bx, (psegcs32) + int 0x31 ! set cs linear address + jc bad_dpmi + + popa + cli ! atomically switch stacks back + mov ss, (dpmi_ss) + o32 mov esp, (dpmi_ebp) + mov ds, (psegds32) + sti + + o32 retf + bad_dpmi: mov si, bad_dpmi_msg jmp exit_with_error @@ -250,8 +332,6 @@ int21: mov bx, (dpmi_ebx) mov cx, (dpmi_ecx) mov dx, (dpmi_edx) - push (dpmi_flags) - popf ret bad_dpmi_msg: @@ -260,7 +340,7 @@ no_file_msg: .asciz "Couldn't open .exe" no_dpmi_msg: .asciz "No DPMI host installed" -.align 2 +.align 4 text_top: exe_text_pages = [text_top - exe_header + 511] / 512 @@ -294,9 +374,12 @@ rseg: .space 2 ! real mode pspseg: .space 2 ! real mode psegcs: .space 2 ! protected mode 16-bit code segment psegds: .space 2 ! protected mode 16-bit data segment +psegcs32: .space 2 ! protected mode 32-bit code segment +psegds32: .space 2 ! protected mode 32-bit data segment +pmemaddr: .space 4 ! protected mode linear memory address pmemhandle: .space 4 ! protected mode linear memory handle +pmemlen: .space 4 ! protected mode linear memory length fh: .space 2 -textlen: .space 4 .space 128 stack: From 680b6b9857d10e79038a77e2f92c87da4716d183 Mon Sep 17 00:00:00 2001 From: David Given Date: Thu, 11 Aug 2022 23:36:23 +0200 Subject: [PATCH 13/20] Marshal the environment, command line and PSP into 32-bit memory. --- plat/msdos386/boot.s | 101 +++++++++++++++++++++++++------------------ 1 file changed, 59 insertions(+), 42 deletions(-) diff --git a/plat/msdos386/boot.s b/plat/msdos386/boot.s index 858785558..618e17163 100644 --- a/plat/msdos386/boot.s +++ b/plat/msdos386/boot.s @@ -56,6 +56,7 @@ begtext: mov es, ax o16 mov bx, ax o16 mov (.doshandle), bx + mov es, bx xor ecx, ecx xor edx, edx @@ -76,63 +77,79 @@ begtext: movb ah, 0x62 int 0x21 - movzx ebx, bx - shl ebx, 4 ! convert to linear address - mov (.psp), ebx + movzx esi, bx + shl esi, 4 ! convert to linear address - ! Get the size of the environment variables plus (if present) the - ! program name. Also count the number of environment variables. - xor di, di - mov es, 0x002C(di) - ! ax = 0 from above - cwd ! dx = count of env. vars. - ! cx = 0 from above - dec cx ! cx = max. str. bytes to scan - scasb ! handle special case of empty env. - jz is_empty_env -size_env: - inc dx - repnz scasb + ! Copy the whole thing into 32-bit memory. + + mov ecx, 0x100/4 + mov edi, _psp + cld +1: + eseg lods + mov (edi), eax + add edi, 4 + loop 1b + + ! Find the environment. + + mov es, (_psp + 0x002C) ! converted to pmode segment + + ! Count the size of the environment variable block. + + xorb al, al ! byte to test for + xor edi, edi + xor edx, edx + cld + mov ecx, -1 scasb - jnz size_env -is_empty_env: - cmp bp, 2 - jz no_argv0 - scasw + jz 2f ! empty environment +1: repnz scasb -no_argv0: + inc edx + scasb + jnz 1b +2: + add edi, 2 ! skip the mysterious word + repnz scasb ! program name - ! Copy out the environment variables and (possibly) program name - ! onto the stack. - mov si, di - dec si + ! Copy the whole environment block onto the stack. + + mov esi, edi + add esi, 3 + and esi, ~3 ! round up + jz empty_environment + mov ecx, esi + shr ecx, 2 ! number of dwords std -copy_env: - and si, -2 - eseg lodsw - push ax - jnz copy_env - mov cx, sp + sub esi, 4 +1: + eseg lods + push eax + loop 1b +empty_environment: + mov ecx, esp ! environment data ! Reset DF and es properly. + cld push ss pop es ! Reserve space for argc and the argv and envp pointers on the ! stack. These will be passed to __m_a_i_n later. - sub sp, 6 - mov ax, sp + + sub esp, 3*4 + mov eax, esp ! Build up argc, argv[], and envp[]. - push ax ! output buffer for argc, argv, envp - push bp ! MS-DOS version - push cx ! env. string data - push dx ! count of env. vars. - mov ax, 0x0080 - push ax ! raw command line + push eax ! output buffer for argc, argv, envp + push 3 ! MS-DOS version + push ecx ! env. string data + push edx ! count of env. vars. + push _psp+0x80 ! raw command line call __sys_initmain - add sp, 10 + add esp, 5*4 ! Bail out if something went wrong. test ax, ax @@ -190,7 +207,7 @@ no_room_msg: .ascii 'No room$' .comm _errno, 4 .comm .doshandle, 2 -.comm .psp, 4 +.comm _psp, 256 .sect .bss .space 512 From 48398b072a5e9e756a777e02712114ecb9fa832a Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 17 Aug 2022 22:34:06 +0200 Subject: [PATCH 14/20] write() system calls work; start going through the libsys. --- plat/msdos386/boot.s | 34 ++++++--- plat/msdos386/descr | 1 - plat/msdos386/libsys/build.lua | 3 +- plat/msdos386/libsys/close.s | 4 +- plat/msdos386/libsys/getpid.s | 4 +- plat/msdos386/libsys/isatty.s | 14 ++-- plat/msdos386/libsys/rename.s | 1 + plat/msdos386/libsys/sys_exists.s | 1 + plat/msdos386/libsys/sys_getdate.s | 1 + plat/msdos386/libsys/sys_gettime.s | 1 + plat/msdos386/libsys/sys_isopen.s | 1 + plat/msdos386/libsys/sys_isreadyr.s | 1 + plat/msdos386/libsys/sys_rawcreat.s | 1 + plat/msdos386/libsys/sys_rawlseek.s | 1 + plat/msdos386/libsys/sys_rawopen.s | 1 + .../libsys/{sys_rawrw.s => sys_rawread.s} | 21 +++--- plat/msdos386/libsys/sys_rawwrite.s | 70 +++++++++++++++++++ plat/msdos386/libsys/sys_xret.s | 31 +++++--- plat/msdos386/stub.s | 30 ++++++-- 19 files changed, 172 insertions(+), 49 deletions(-) rename plat/msdos386/libsys/{sys_rawrw.s => sys_rawread.s} (56%) create mode 100644 plat/msdos386/libsys/sys_rawwrite.s diff --git a/plat/msdos386/boot.s b/plat/msdos386/boot.s index 618e17163..282dcb866 100644 --- a/plat/msdos386/boot.s +++ b/plat/msdos386/boot.s @@ -18,15 +18,24 @@ begtext: ! On entry, the stub has cs and ds pointing at the 32-bit ! segment, but ss is still pointing at the 16-bit segment. ! - ! si:di memory handle of linear block ! ax: pmode code segment of stub - ! dx: pointer to realloc routine - ! fs: data segment (just a clone of the code segment) + ! bx: pmode data segment of stub + ! cx: rmode segment of stub + ! dx: pointer to realloc routine (in stub)e + ! si: pointer to interrupt routine (in stub) + ! di: pointer to transfer buffer (in stub) ! Resize the segment to include the BSS. o16 cseg mov (realloc_ptr+4), ax cseg mov (realloc_ptr+0), edx + cseg o16 mov (pmode_cs), ax + cseg o16 mov (pmode_ds), bx + cseg o16 mov (rmode), cx + cseg o16 mov (interrupt_ptr+4), ax + cseg mov (interrupt_ptr+0), esi + cseg o16 mov (transfer_buffer_ptr), di + mov eax, endbss cseg callf (realloc_ptr) @@ -180,10 +189,19 @@ al_exit: movb ah, 0x4c int 0x21 - ! This must be in the code segment due to bootstrap issues. -realloc_ptr: - .data2 0 - .data4 0 + ! These must be in the code segment due to bootstrap issues. +realloc_ptr: .space 6 ! far +interrupt_ptr: .space 6 ! far +transfer_buffer_ptr: .space 2 ! near +rmode: .space 2 +pmode_cs: .space 2 +pmode_ds: .space 2 + +.define interrupt_ptr +.define rmode +.define pmode_cs +.define pmode_ds +.define transfer_buffer_ptr ! Define symbols at the beginning of our various segments, so that we can find ! them. (Except .text, which has already been done.) @@ -210,7 +228,7 @@ no_room_msg: .ascii 'No room$' .comm _psp, 256 .sect .bss - .space 512 + .space 32*1024 .stack: ! vim: ts=4 sw=4 et ft=asm diff --git a/plat/msdos386/descr b/plat/msdos386/descr index 718424e21..d7be3eb1e 100644 --- a/plat/msdos386/descr +++ b/plat/msdos386/descr @@ -39,7 +39,6 @@ name as program {EM}/lib/ack/{PLATFORM}/as args - -o > < prep cond - end name led from .o.a diff --git a/plat/msdos386/libsys/build.lua b/plat/msdos386/libsys/build.lua index 70c7eaa17..4d349eb0f 100644 --- a/plat/msdos386/libsys/build.lua +++ b/plat/msdos386/libsys/build.lua @@ -16,7 +16,8 @@ acklibrary { "./sys_rawcreat.s", "./sys_rawlseek.s", "./sys_rawopen.s", - "./sys_rawrw.s", + "./sys_rawread.s", + "./sys_rawwrite.s", "./sys_xret.s", "./unlink.s", "plat/msdos/libsys+srcs", diff --git a/plat/msdos386/libsys/close.s b/plat/msdos386/libsys/close.s index b8c2f8a15..5e52a638b 100644 --- a/plat/msdos386/libsys/close.s +++ b/plat/msdos386/libsys/close.s @@ -16,8 +16,8 @@ .define _close _close: - mov bx, sp - mov bx, 2(bx) + mov ebx, sp + mov ebx, 4(ebx) movb ah, 0x3E int 0x21 jmp .sys_zret diff --git a/plat/msdos386/libsys/getpid.s b/plat/msdos386/libsys/getpid.s index 5aa80638b..d2a250491 100644 --- a/plat/msdos386/libsys/getpid.s +++ b/plat/msdos386/libsys/getpid.s @@ -39,7 +39,7 @@ _getpid: jnc .eur_dos movb ah, 0x51 int 0x21 - xchg bx, ax + xchg ebx, eax .eur_dos: - xor dx, dx + xor edx, edx ret diff --git a/plat/msdos386/libsys/isatty.s b/plat/msdos386/libsys/isatty.s index bd2e195e6..7ed92fffd 100644 --- a/plat/msdos386/libsys/isatty.s +++ b/plat/msdos386/libsys/isatty.s @@ -16,22 +16,22 @@ .define _isatty _isatty: - mov bx, sp - mov bx, 2(bx) - mov ax, 0x4400 + mov ebx, sp + mov ebx, 4(ebx) + o16 mov ax, 0x4400 int 0x21 jc error testb dl, dl jz not_tty - mov ax, 1 + mov eax, 1 ret not_tty: mov (_errno), 25 ! ENOTTY not_tty_2: - xor ax, ax + xor eax, eax ret error: - push ax + push eax call __sys_seterrno - pop cx + pop ecx jmp not_tty_2 diff --git a/plat/msdos386/libsys/rename.s b/plat/msdos386/libsys/rename.s index edb14266b..1550b73db 100644 --- a/plat/msdos386/libsys/rename.s +++ b/plat/msdos386/libsys/rename.s @@ -16,6 +16,7 @@ .define _rename _rename: + int 3 mov bx, sp push di mov dx, 2(bx) diff --git a/plat/msdos386/libsys/sys_exists.s b/plat/msdos386/libsys/sys_exists.s index e282ef687..8786f4c2a 100644 --- a/plat/msdos386/libsys/sys_exists.s +++ b/plat/msdos386/libsys/sys_exists.s @@ -16,6 +16,7 @@ .define __sys_exists __sys_exists: + int 3 mov bx, sp mov dx, 2(bx) mov ax, 0x4300 diff --git a/plat/msdos386/libsys/sys_getdate.s b/plat/msdos386/libsys/sys_getdate.s index 41d69fc85..eeb118923 100644 --- a/plat/msdos386/libsys/sys_getdate.s +++ b/plat/msdos386/libsys/sys_getdate.s @@ -16,6 +16,7 @@ .define __sys_getdate __sys_getdate: + int 3 movb ah, 0x2a int 0x21 mov bx, sp diff --git a/plat/msdos386/libsys/sys_gettime.s b/plat/msdos386/libsys/sys_gettime.s index d062fad8d..d3ea65847 100644 --- a/plat/msdos386/libsys/sys_gettime.s +++ b/plat/msdos386/libsys/sys_gettime.s @@ -16,6 +16,7 @@ .define __sys_gettime __sys_gettime: + int 3 movb ah, 0x2c int 0x21 mov bx, sp diff --git a/plat/msdos386/libsys/sys_isopen.s b/plat/msdos386/libsys/sys_isopen.s index 5ce49ed45..5da95a44e 100644 --- a/plat/msdos386/libsys/sys_isopen.s +++ b/plat/msdos386/libsys/sys_isopen.s @@ -17,6 +17,7 @@ .define __sys_isopen __sys_isopen: + int 3 mov bx, sp mov bx, 2(bx) mov ax, 0x4400 diff --git a/plat/msdos386/libsys/sys_isreadyr.s b/plat/msdos386/libsys/sys_isreadyr.s index b5d0800ee..9a400859d 100644 --- a/plat/msdos386/libsys/sys_isreadyr.s +++ b/plat/msdos386/libsys/sys_isreadyr.s @@ -17,6 +17,7 @@ .define __sys_isreadyr __sys_isreadyr: + int 3 mov bx, sp mov ax, 0x4406 mov bx, 2(bx) diff --git a/plat/msdos386/libsys/sys_rawcreat.s b/plat/msdos386/libsys/sys_rawcreat.s index 67bc34e59..0d765a27d 100644 --- a/plat/msdos386/libsys/sys_rawcreat.s +++ b/plat/msdos386/libsys/sys_rawcreat.s @@ -16,6 +16,7 @@ .define __sys_rawcreat __sys_rawcreat: + int 3 movb ah, 0x3c mov bx, sp mov dx, 2(bx) diff --git a/plat/msdos386/libsys/sys_rawlseek.s b/plat/msdos386/libsys/sys_rawlseek.s index 992c4c655..06a7783a7 100644 --- a/plat/msdos386/libsys/sys_rawlseek.s +++ b/plat/msdos386/libsys/sys_rawlseek.s @@ -16,6 +16,7 @@ .define __sys_rawlseek __sys_rawlseek: + int 3 movb ah, 0x42 mov bx, sp mov dx, 4(bx) diff --git a/plat/msdos386/libsys/sys_rawopen.s b/plat/msdos386/libsys/sys_rawopen.s index 301e2fded..5fae1bba4 100644 --- a/plat/msdos386/libsys/sys_rawopen.s +++ b/plat/msdos386/libsys/sys_rawopen.s @@ -16,6 +16,7 @@ .define __sys_rawopen __sys_rawopen: + int 3 movb ah, 0x3d mov bx, sp mov dx, 2(bx) diff --git a/plat/msdos386/libsys/sys_rawrw.s b/plat/msdos386/libsys/sys_rawread.s similarity index 56% rename from plat/msdos386/libsys/sys_rawrw.s rename to plat/msdos386/libsys/sys_rawread.s index a306d6528..d7c14aa54 100644 --- a/plat/msdos386/libsys/sys_rawrw.s +++ b/plat/msdos386/libsys/sys_rawread.s @@ -12,7 +12,13 @@ .sect .text -! Read/write bytes to/to a file descriptor. These routines do not do any +.extern pmode_ds +.extern pmode_cs +.extern rmode +.extern transfer_buffer_ptr +.extern interrupt_ptr + +! Read bytes from a file descriptor. These routines do not do any ! translation between CRLF and LF line endings. ! ! Note that, for MS-DOS, a raw "write" request of zero bytes will truncate @@ -20,14 +26,5 @@ .define __sys_rawread __sys_rawread: - movb ah, 0x3f - .data1 0x3d ! eat up the next instruction -.define __sys_rawwrite -__sys_rawwrite: - movb ah, 0x40 - mov bx, sp - mov dx, 4(bx) - mov cx, 6(bx) - mov bx, 2(bx) - int 0x21 - jmp .sys_axret + int 3 + diff --git a/plat/msdos386/libsys/sys_rawwrite.s b/plat/msdos386/libsys/sys_rawwrite.s new file mode 100644 index 000000000..e13e5e52c --- /dev/null +++ b/plat/msdos386/libsys/sys_rawwrite.s @@ -0,0 +1,70 @@ +# +! $Source$ +! $State$ +! $Revision$ + +! Declare segments (the order is important). + +.sect .text +.sect .rom +.sect .data +.sect .bss + +.sect .text + +.extern pmode_ds +.extern pmode_cs +.extern rmode +.extern transfer_buffer_ptr +.extern interrupt_ptr + +! Write bytes to/to a file descriptor. These routines do not do any +! translation between CRLF and LF line endings. +! +! Note that, for MS-DOS, a raw "write" request of zero bytes will truncate +! (or extend) the file to the current file position. + +.define __sys_rawwrite +__sys_rawwrite: + enter 4, 0 +amount_transferred = -1*4 +file_handle = 2*4 +read_buffer = 3*4 +amount_to_write = 4*4 + + mov es, (pmode_ds) + mov amount_transferred(ebp), 0 + +mainloop: + mov ecx, 32*1024 + cmp amount_to_write(ebp), ecx + jge 2f + mov ecx, amount_to_write(ebp) + test ecx, ecx + jz exit +2: + ! Copy ecx bytes into the transfer buffer. + + push ecx + mov esi, read_buffer(ebp) + movzx edi, (transfer_buffer_ptr) + rep movsb + pop ecx + + movb ah, 0x40 + o16 mov dx, (transfer_buffer_ptr) + o16 mov bx, file_handle(ebp) + or ebx, 0x210000 + callf (interrupt_ptr) + movzx eax, ax + + add read_buffer(ebp), eax + add amount_transferred(ebp), eax + sub amount_to_write(ebp), eax + jmp mainloop + +exit: + mov eax, amount_to_write(ebp) + leave + ret + diff --git a/plat/msdos386/libsys/sys_xret.s b/plat/msdos386/libsys/sys_xret.s index 57f407ef4..20c2b454b 100644 --- a/plat/msdos386/libsys/sys_xret.s +++ b/plat/msdos386/libsys/sys_xret.s @@ -13,29 +13,38 @@ .sect .text ! .sys_zret: if the carry flag is set, then set `errno' from the DOS error -! code in ax, and return a shortword -1. If the carry flag is clear, just -! return a shortword zero. +! code in ax, and return an int -1. If the carry flag is clear, just +! return an int zero. ! ! .sys_axret: if the carry flag is set, then set `errno' from the DOS error ! code in ax, and return a shortword -1. If the carry flag is clear, just ! return ax as a return value. ! -! .sys_dxaxret: same as .sys_axret, but return a longword -1 or dx:ax as a -! return value. +! .sys_dxaxret: same as .sys_axret, but return -1 or dx:ax as a return value. .extern .sys_zret .extern .sys_axret .extern .sys_dxaxret .sys_zret: jc error - xor ax, ax + xor eax, eax no_error: ret + .sys_axret: -.sys_dxaxret: - jnc no_error -error: - push ax - call __sys_seterrno - pop cx + jc error + ret + +.sys_dxaxret: + jc error + shl edx, 16 + o16 mov dx, ax + mov eax, edx + ret + +error: + movzx eax, ax + push eax + call __sys_seterrno + pop ecx ret diff --git a/plat/msdos386/stub.s b/plat/msdos386/stub.s index 863d5d8f7..03887ec5d 100644 --- a/plat/msdos386/stub.s +++ b/plat/msdos386/stub.s @@ -210,15 +210,17 @@ exe_start: ! Jump to the new segment and enter 32-bit mode! - mov ax, (psegcs) - mov bx, (psegds) - mov cx, (rseg) + o32 movzx eax, (psegcs) + o32 movzx ebx, (psegds) + o32 movzx ecx, (rseg) o32 mov edx, realloc + o32 mov esi, interruptf + o32 mov edi, transfer_buffer push es pop ds push es push 0 - retf + retf ! 19b ! ALL CODE ABOVE THIS POINT DISCARDED ON ENTRY TO 32-BIT CODE ! (it's reused as the 16-bit stack) @@ -271,6 +273,7 @@ realloc: jc bad_dpmi popa + o32 mov eax, (pmemlen) cli ! atomically switch stacks back mov ss, (dpmi_ss) o32 mov esp, (dpmi_ebp) @@ -309,10 +312,15 @@ exit_with_error: ! Simulate DOS interrupt. int21: + o32 or ebx, 0x210000 + ! Simulate interrupt in the high half of ebx. +interrupt: mov (dpmi_eax), ax mov (dpmi_ebx), bx mov (dpmi_ecx), cx mov (dpmi_edx), dx + mov (dpmi_esi), si + mov (dpmi_edi), di mov ax, (rseg) mov (dpmi_ds), ax push es @@ -324,16 +332,28 @@ int21: pop es mov di, dpmi_edi mov ax, 0x300 - mov bx, 0x21 + o32 shr ebx, 16 int 0x31 ! simulate DOS interrupt pop ds pop es + pushf mov ax, (dpmi_eax) mov bx, (dpmi_ebx) mov cx, (dpmi_ecx) mov dx, (dpmi_edx) + mov si, (dpmi_esi) + mov di, (dpmi_edi) + popf ret +! Far call wrapper around interrupt. +interruptf: + push ds + cseg mov ds, (psegds) + call interrupt + pop ds + o32 retf + bad_dpmi_msg: .asciz "DPMI error during setup" no_file_msg: From cc356b5c75053b16ddc7cc41a7dc6749de41b9ff Mon Sep 17 00:00:00 2001 From: David Given Date: Thu, 18 Aug 2022 00:24:08 +0200 Subject: [PATCH 15/20] Programs now start up and can write to the console, but crash when reading. --- plat/msdos386/boot.s | 5 ++- plat/msdos386/libsys/brk.s | 23 +++++++++++ plat/msdos386/libsys/build.lua | 5 ++- plat/msdos386/libsys/{brk.c => sbrk.c} | 20 --------- plat/msdos386/libsys/sys_isreadyr.s | 8 ++-- plat/msdos386/libsys/sys_rawread.s | 57 +++++++++++++++++++++++++- plat/msdos386/libsys/sys_rawwrite.s | 24 +++++++---- plat/msdos386/stub.s | 12 +++--- 8 files changed, 111 insertions(+), 43 deletions(-) create mode 100644 plat/msdos386/libsys/brk.s rename plat/msdos386/libsys/{brk.c => sbrk.c} (61%) diff --git a/plat/msdos386/boot.s b/plat/msdos386/boot.s index 282dcb866..b30b6594c 100644 --- a/plat/msdos386/boot.s +++ b/plat/msdos386/boot.s @@ -36,7 +36,7 @@ begtext: cseg mov (interrupt_ptr+0), esi cseg o16 mov (transfer_buffer_ptr), di - mov eax, endbss + mov eax, __end cseg callf (realloc_ptr) ! Clear BSS. @@ -161,7 +161,7 @@ empty_environment: add esp, 5*4 ! Bail out if something went wrong. - test ax, ax + test eax, eax jnz no_room ! argc, argv, and envp are now at the stack top. Now go. @@ -197,6 +197,7 @@ rmode: .space 2 pmode_cs: .space 2 pmode_ds: .space 2 +.define realloc_ptr .define interrupt_ptr .define rmode .define pmode_cs diff --git a/plat/msdos386/libsys/brk.s b/plat/msdos386/libsys/brk.s new file mode 100644 index 000000000..0e3170467 --- /dev/null +++ b/plat/msdos386/libsys/brk.s @@ -0,0 +1,23 @@ +! Declare segments (the order is important). + +.sect .text +.sect .rom +.sect .data +.sect .bss + +.sect .text + +.extern realloc_ptr + +.define _brk +_brk: + enter 0, 0 +newsize = 2*4 + + mov eax, newsize(ebp) + callf (realloc_ptr) + xor eax, eax + leave + ret + + diff --git a/plat/msdos386/libsys/build.lua b/plat/msdos386/libsys/build.lua index 4d349eb0f..71ac521b8 100644 --- a/plat/msdos386/libsys/build.lua +++ b/plat/msdos386/libsys/build.lua @@ -1,13 +1,14 @@ acklibrary { name = "lib", srcs = { - "./brk.c", + "./_hol0.s", + "./brk.s", "./close.s", "./errno.s", "./getpid.s", - "./_hol0.s", "./isatty.s", "./rename.s", + "./sbrk.c", "./sys_exists.s", "./sys_getdate.s", "./sys_gettime.s", diff --git a/plat/msdos386/libsys/brk.c b/plat/msdos386/libsys/sbrk.c similarity index 61% rename from plat/msdos386/libsys/brk.c rename to plat/msdos386/libsys/sbrk.c index ab333e550..988d406f3 100644 --- a/plat/msdos386/libsys/brk.c +++ b/plat/msdos386/libsys/sbrk.c @@ -8,29 +8,9 @@ #include #include "libsys.h" -#define STACK_BUFFER 128 /* number of bytes to leave for stack */ - extern char _end[1]; static char* current = _end; -int brk(void* newend) -{ - /* This variable is used to figure out the current stack pointer, - * by taking its address. */ - char dummy; - char* p = newend; - - if ((p > (&dummy - STACK_BUFFER)) || - (p < _end)) - { - errno = ENOMEM; - return -1; - } - - current = p; - return 0; -} - void* sbrk(int increment) { char* old; diff --git a/plat/msdos386/libsys/sys_isreadyr.s b/plat/msdos386/libsys/sys_isreadyr.s index 9a400859d..ff3960b27 100644 --- a/plat/msdos386/libsys/sys_isreadyr.s +++ b/plat/msdos386/libsys/sys_isreadyr.s @@ -17,13 +17,13 @@ .define __sys_isreadyr __sys_isreadyr: - int 3 - mov bx, sp - mov ax, 0x4406 - mov bx, 2(bx) + mov ebx, sp + mov eax, 0x4406 + mov ebx, 4(ebx) int 0x21 jnc ok movb al, 0 ok: cbw + cwd ret diff --git a/plat/msdos386/libsys/sys_rawread.s b/plat/msdos386/libsys/sys_rawread.s index d7c14aa54..c8ba4bea0 100644 --- a/plat/msdos386/libsys/sys_rawread.s +++ b/plat/msdos386/libsys/sys_rawread.s @@ -26,5 +26,60 @@ .define __sys_rawread __sys_rawread: - int 3 + enter 4, 0 +amount_transferred = -1*4 +file_handle = 2*4 +write_buffer = 3*4 +amount_to_read = 4*4 + + mov amount_transferred(ebp), 0 + +mainloop: + mov eax, amount_to_read(ebp) + test eax, eax + jz exit + + mov ecx, 32*1024 + cmp eax, ecx + jge 2f + mov ecx, eax +2: + + ! Read from DOS into the transfer buffer. + + movb ah, 0x3f + o16 mov dx, (transfer_buffer_ptr) + o16 mov bx, file_handle(ebp) + mov ecx, 0x80 + or ebx, 0x210000 + callf (interrupt_ptr) + jc exit + test eax, eax + jz exit + + ! Copy eax bytes out of the transfer buffer. + + mov ecx, eax + push eax + movzx esi, (transfer_buffer_ptr) + mov edi, write_buffer(ebp) + mov es, (pmode_ds) + cld +1: + eseg lods + movb (edi), al + add edi, 4 + loop 1b + pop eax + + add write_buffer(ebp), eax + add amount_transferred(ebp), eax + sub amount_to_read(ebp), eax + jmp mainloop + +exit: + mov eax, amount_transferred(ebp) + leave + ret + diff --git a/plat/msdos386/libsys/sys_rawwrite.s b/plat/msdos386/libsys/sys_rawwrite.s index e13e5e52c..bef6481b2 100644 --- a/plat/msdos386/libsys/sys_rawwrite.s +++ b/plat/msdos386/libsys/sys_rawwrite.s @@ -32,31 +32,39 @@ file_handle = 2*4 read_buffer = 3*4 amount_to_write = 4*4 - mov es, (pmode_ds) mov amount_transferred(ebp), 0 mainloop: - mov ecx, 32*1024 - cmp amount_to_write(ebp), ecx - jge 2f - mov ecx, amount_to_write(ebp) - test ecx, ecx + mov eax, amount_to_write(ebp) + test eax, eax jz exit + + mov ecx, 32*1024 + cmp eax, ecx + jge 2f + mov ecx, eax 2: + ! Copy ecx bytes into the transfer buffer. push ecx mov esi, read_buffer(ebp) movzx edi, (transfer_buffer_ptr) + mov es, (pmode_ds) + cld rep movsb pop ecx + ! Write from the transfer buffer to DOS. + movb ah, 0x40 o16 mov dx, (transfer_buffer_ptr) o16 mov bx, file_handle(ebp) or ebx, 0x210000 callf (interrupt_ptr) - movzx eax, ax + jc exit + + ! Update counters and go again. add read_buffer(ebp), eax add amount_transferred(ebp), eax @@ -64,7 +72,7 @@ mainloop: jmp mainloop exit: - mov eax, amount_to_write(ebp) + mov eax, amount_transferred(ebp) leave ret diff --git a/plat/msdos386/stub.s b/plat/msdos386/stub.s index 03887ec5d..725d3431e 100644 --- a/plat/msdos386/stub.s +++ b/plat/msdos386/stub.s @@ -337,12 +337,12 @@ interrupt: pop ds pop es pushf - mov ax, (dpmi_eax) - mov bx, (dpmi_ebx) - mov cx, (dpmi_ecx) - mov dx, (dpmi_edx) - mov si, (dpmi_esi) - mov di, (dpmi_edi) + o32 movzx eax, (dpmi_eax) + o32 movzx ebx, (dpmi_ebx) + o32 movzx ecx, (dpmi_ecx) + o32 movzx edx, (dpmi_edx) + o32 movzx esi, (dpmi_esi) + o32 movzx edi, (dpmi_edi) popf ret From 5329c98b81d7760e7934695de3e32abd8d2e8e8a Mon Sep 17 00:00:00 2001 From: David Given Date: Thu, 18 Aug 2022 21:21:33 +0200 Subject: [PATCH 16/20] Simplify and fix reading and writing so they seem to work. --- plat/msdos/libsys/read.c | 56 +++++++++++++------------ plat/msdos/libsys/write.c | 59 ++++++++++++++++---------- plat/msdos386/boot.s | 2 +- plat/msdos386/libsys/sys_rawread.s | 35 ++++++---------- plat/msdos386/libsys/sys_rawwrite.s | 65 ++++++++++++----------------- plat/msdos386/stub.s | 16 ++++--- 6 files changed, 113 insertions(+), 120 deletions(-) diff --git a/plat/msdos/libsys/read.c b/plat/msdos/libsys/read.c index 5075958bd..bed9fcd14 100644 --- a/plat/msdos/libsys/read.c +++ b/plat/msdos/libsys/read.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -16,9 +17,7 @@ ssize_t read(int fd, void* buffer, size_t count) ssize_t r, tot; size_t left; int eof = 0; - - if (!count || _sys_getmode(fd) == O_BINARY) - return _sys_rawread(fd, buffer, count); + bool text = _sys_getmode(fd) == O_TEXT; if (_sys_iseof(fd)) return 0; @@ -47,33 +46,36 @@ ssize_t read(int fd, void* buffer, size_t count) if (r <= 0) return tot ? tot : r; - q = memchr(p, 0x1a, (size_t)r); - if (q) + if (text) { - _sys_rawlseek(fd, (off_t)(q - p) - r, SEEK_CUR); - r = q - p; - eof = 1; - _sys_seteof(fd, 1); - } - - q = memchr(p, '\r', (size_t)r); - if (!q) - return tot + r; - - tot += q - p; - left = r - (q + 1 - p); - p = q; - ++q; - - while (left) - { - char c = *q++; - if (c != '\r') + q = memchr(p, 0x1a, (size_t)r); + if (q) { - *p++ = c; - ++tot; + _sys_rawlseek(fd, (off_t)(q - p) - r, SEEK_CUR); + r = q - p; + eof = 1; + _sys_seteof(fd, 1); + } + + q = memchr(p, '\r', (size_t)r); + if (!q) + return tot + r; + + tot += q - p; + left = r - (q + 1 - p); + p = q; + ++q; + + while (left) + { + char c = *q++; + if (c != '\r') + { + *p++ = c; + ++tot; + } + --left; } - --left; } } while (tot < count && !eof && _sys_isreadyr(fd)); diff --git a/plat/msdos/libsys/write.c b/plat/msdos/libsys/write.c index fc744b256..cfc764246 100644 --- a/plat/msdos/libsys/write.c +++ b/plat/msdos/libsys/write.c @@ -20,42 +20,55 @@ ssize_t write(int fd, void* buffer, size_t count) if (!count) return 0; - if (_sys_getmode(fd) == O_BINARY) - return _sys_rawwrite(fd, buffer, count); - - /* If the file descriptor is an O_TEXT fd, translate LFs to CRLFs. */ p = buffer; left = count; tot = 0; - while (left) - { - q = memchr(p, '\n', left); - if (!q) - return _sys_rawwrite(fd, p, left); - n = q - p; - if (n) + if (_sys_getmode(fd) == O_BINARY) + { + while (left) { - r = _sys_rawwrite(fd, p, n); + r = _sys_rawwrite(fd, p, left); if (r <= 0) return tot ? tot : r; tot += r; p += r; left -= r; - if (r != n) - break; } - - r = _sys_rawwrite(fd, crlf, sizeof crlf); - if (r != 2) + } + else + { + /* If the file descriptor is an O_TEXT fd, translate LFs to CRLFs. */ + while (left) { - if (r > 0) - r = 0; - return tot ? tot : r; + q = memchr(p, '\n', left); + if (!q) + return _sys_rawwrite(fd, p, left); + + n = q - p; + if (n) + { + r = _sys_rawwrite(fd, p, n); + if (r <= 0) + return tot ? tot : r; + tot += r; + p += r; + left -= r; + if (r != n) + break; + } + + r = _sys_rawwrite(fd, crlf, sizeof crlf); + if (r != 2) + { + if (r > 0) + r = 0; + return tot ? tot : r; + } + ++tot; + ++p; + --left; } - ++tot; - ++p; - --left; } return tot; } diff --git a/plat/msdos386/boot.s b/plat/msdos386/boot.s index b30b6594c..6e1b02add 100644 --- a/plat/msdos386/boot.s +++ b/plat/msdos386/boot.s @@ -166,7 +166,7 @@ empty_environment: ! argc, argv, and envp are now at the stack top. Now go. call __m_a_i_n - add sp, 6 + add sp, 3*4 push ax call _exit diff --git a/plat/msdos386/libsys/sys_rawread.s b/plat/msdos386/libsys/sys_rawread.s index c8ba4bea0..c54410347 100644 --- a/plat/msdos386/libsys/sys_rawread.s +++ b/plat/msdos386/libsys/sys_rawread.s @@ -26,19 +26,12 @@ .define __sys_rawread __sys_rawread: - enter 4, 0 -amount_transferred = -1*4 + enter 0, 0 file_handle = 2*4 write_buffer = 3*4 amount_to_read = 4*4 - mov amount_transferred(ebp), 0 - -mainloop: mov eax, amount_to_read(ebp) - test eax, eax - jz exit - mov ecx, 32*1024 cmp eax, ecx jge 2f @@ -53,33 +46,31 @@ mainloop: mov ecx, 0x80 or ebx, 0x210000 callf (interrupt_ptr) - jc exit - test eax, eax - jz exit + jnc success + + ! Process errors. + + push eax + call __sys_seterrno + leave + ret +success: ! Copy eax bytes out of the transfer buffer. - mov ecx, eax push eax + mov ecx, eax movzx esi, (transfer_buffer_ptr) mov edi, write_buffer(ebp) mov es, (pmode_ds) cld 1: - eseg lods + eseg lodsb movb (edi), al - add edi, 4 + inc edi loop 1b pop eax - add write_buffer(ebp), eax - add amount_transferred(ebp), eax - sub amount_to_read(ebp), eax - jmp mainloop - -exit: - mov eax, amount_transferred(ebp) leave ret - diff --git a/plat/msdos386/libsys/sys_rawwrite.s b/plat/msdos386/libsys/sys_rawwrite.s index bef6481b2..5451670fe 100644 --- a/plat/msdos386/libsys/sys_rawwrite.s +++ b/plat/msdos386/libsys/sys_rawwrite.s @@ -26,53 +26,42 @@ .define __sys_rawwrite __sys_rawwrite: - enter 4, 0 -amount_transferred = -1*4 + enter 0, 0 file_handle = 2*4 read_buffer = 3*4 amount_to_write = 4*4 - mov amount_transferred(ebp), 0 - -mainloop: - mov eax, amount_to_write(ebp) - test eax, eax - jz exit - - mov ecx, 32*1024 - cmp eax, ecx - jge 2f - mov ecx, eax + mov eax, amount_to_write(ebp) + mov ecx, 32*1024 ! size of transfer buffer + cmp eax, ecx + jge 2f + mov ecx, eax 2: - ! Copy ecx bytes into the transfer buffer. + ! Copy ecx bytes into the transfer buffer. - push ecx - mov esi, read_buffer(ebp) - movzx edi, (transfer_buffer_ptr) - mov es, (pmode_ds) - cld - rep movsb - pop ecx + push ecx + mov esi, read_buffer(ebp) + movzx edi, (transfer_buffer_ptr) + mov es, (pmode_ds) + cld + rep movsb + pop ecx - ! Write from the transfer buffer to DOS. + ! Write from the transfer buffer to DOS. - movb ah, 0x40 - o16 mov dx, (transfer_buffer_ptr) - o16 mov bx, file_handle(ebp) - or ebx, 0x210000 - callf (interrupt_ptr) - jc exit - - ! Update counters and go again. - - add read_buffer(ebp), eax - add amount_transferred(ebp), eax - sub amount_to_write(ebp), eax - jmp mainloop + movb ah, 0x40 + o16 mov dx, (transfer_buffer_ptr) + o16 mov bx, file_handle(ebp) + or ebx, 0x210000 + callf (interrupt_ptr) + jnc exit + push eax + call __sys_seterrno exit: - mov eax, amount_transferred(ebp) - leave - ret + leave + ret + +! vim: sw=4 ts=4 et diff --git a/plat/msdos386/stub.s b/plat/msdos386/stub.s index 725d3431e..35b9e8e40 100644 --- a/plat/msdos386/stub.s +++ b/plat/msdos386/stub.s @@ -116,7 +116,7 @@ exe_start: callf (pmode_switch) jc bad_dpmi - ! We're now in protected mode. (ae) + ! We're now in protected mode. mov (psegcs), cs mov (psegds), ds @@ -222,10 +222,6 @@ exe_start: push 0 retf ! 19b - ! ALL CODE ABOVE THIS POINT DISCARDED ON ENTRY TO 32-BIT CODE - ! (it's reused as the 16-bit stack) -stack16: - ! Helper routine which reallocates the linear block that the 32-bit code ! is running from. This can't happen from inside the 32-bit code itself ! because it might move. @@ -238,7 +234,7 @@ realloc: o32 mov (dpmi_ebp), esp ! yes, saving esp into the ebp field mov (dpmi_ss), ss mov ss, (psegds) - mov sp, stack16 + mov sp, dosstack sti pusha @@ -323,10 +319,10 @@ interrupt: mov (dpmi_edi), di mov ax, (rseg) mov (dpmi_ds), ax + mov (dpmi_ss), ax push es push ds - xor ax, ax - mov (dpmi_ss), ax ! zero stack: DPMI host allocates one. + mov ax, dosstack ! auto stack is too small mov (dpmi_sp), ax push ds pop es @@ -401,8 +397,10 @@ pmemhandle: .space 4 ! protected mode linear memory handle pmemlen: .space 4 ! protected mode linear memory length fh: .space 2 - .space 128 + .space 512 stack: + .space 512 +dosstack: TRANSFER_BUFFER_SIZE = 32*1024 transfer_buffer: From dc1f69be83461b4e8450df1ea1d77fca0186158b Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 19 Aug 2022 00:08:57 +0200 Subject: [PATCH 17/20] Most of read and write now works; filename-based operations partially work; but there's a nasty memory corruption somewhere which needs investigating. --- plat/msdos386/descr | 3 +-- plat/msdos386/libsys/brk.s | 9 ++----- plat/msdos386/libsys/close.s | 4 +-- plat/msdos386/libsys/isatty.s | 2 +- plat/msdos386/libsys/rename.s | 41 ++++++++++++++++++++++++----- plat/msdos386/libsys/sys_exists.s | 11 ++++---- plat/msdos386/libsys/sys_getdate.s | 9 +++---- plat/msdos386/libsys/sys_gettime.s | 9 +++---- plat/msdos386/libsys/sys_isopen.s | 11 ++++---- plat/msdos386/libsys/sys_isreadyr.s | 6 ++--- plat/msdos386/libsys/sys_rawcreat.s | 30 +++++++++++++++++---- plat/msdos386/libsys/sys_rawlseek.s | 11 ++++---- plat/msdos386/libsys/sys_rawopen.s | 30 +++++++++++++++++---- plat/msdos386/libsys/sys_rawread.s | 16 +++++------ plat/msdos386/libsys/sys_rawwrite.s | 11 ++++---- plat/msdos386/libsys/unlink.s | 27 ++++++++++++++++--- plat/msdos386/stub.s | 9 +++---- 17 files changed, 155 insertions(+), 84 deletions(-) diff --git a/plat/msdos386/descr b/plat/msdos386/descr index d7be3eb1e..b6683871b 100644 --- a/plat/msdos386/descr +++ b/plat/msdos386/descr @@ -46,7 +46,7 @@ name led program {EM}/lib/ack/em_led mapflag -l* LNAME={PLATFORMDIR}/lib* mapflag -fp FLOATS={EM}/{ILIB}fp - args {ALIGN} {SEPID} \ + args {ALIGN} \ ({RTS}:.b=-u _i_main) \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ ({RTS}:.ocm.bas.b={PLATFORMDIR}/c-ansi.o) \ @@ -66,7 +66,6 @@ name led {PLATFORMDIR}/libc.a \ {PLATFORMDIR}/libem.a \ {PLATFORMDIR}/libend.a) - linker end name cv diff --git a/plat/msdos386/libsys/brk.s b/plat/msdos386/libsys/brk.s index 0e3170467..3032bc929 100644 --- a/plat/msdos386/libsys/brk.s +++ b/plat/msdos386/libsys/brk.s @@ -7,17 +7,12 @@ .sect .text -.extern realloc_ptr - .define _brk _brk: - enter 0, 0 -newsize = 2*4 - - mov eax, newsize(ebp) + mov ebx, esp + mov eax, 1*4(ebx) callf (realloc_ptr) xor eax, eax - leave ret diff --git a/plat/msdos386/libsys/close.s b/plat/msdos386/libsys/close.s index 5e52a638b..412307b62 100644 --- a/plat/msdos386/libsys/close.s +++ b/plat/msdos386/libsys/close.s @@ -16,8 +16,8 @@ .define _close _close: - mov ebx, sp - mov ebx, 4(ebx) + mov ebx, esp + mov ebx, 1*4(esp) movb ah, 0x3E int 0x21 jmp .sys_zret diff --git a/plat/msdos386/libsys/isatty.s b/plat/msdos386/libsys/isatty.s index 7ed92fffd..794274bfa 100644 --- a/plat/msdos386/libsys/isatty.s +++ b/plat/msdos386/libsys/isatty.s @@ -16,7 +16,7 @@ .define _isatty _isatty: - mov ebx, sp + mov ebx, esp mov ebx, 4(ebx) o16 mov ax, 0x4400 int 0x21 diff --git a/plat/msdos386/libsys/rename.s b/plat/msdos386/libsys/rename.s index 1550b73db..4b43a0d48 100644 --- a/plat/msdos386/libsys/rename.s +++ b/plat/msdos386/libsys/rename.s @@ -16,12 +16,39 @@ .define _rename _rename: - int 3 - mov bx, sp - push di - mov dx, 2(bx) - mov di, 4(bx) + mov ebx, esp + push esi + push edi + + ! Source filename. + + mov esi, 4(ebx) + movzx edi, (transfer_buffer_ptr) + mov es, (pmode_ds) + cld +1: + lodsb + stosb + testb al, al + jnz 1b + + ! Destination filename. + + mov eax, edi + mov esi, 8(ebx) +1: + lodsb + stosb + testb al, al + jnz 1b + + ! Make the DOS call. + + o16 mov dx, (transfer_buffer_ptr) + o16 mov di, ax movb ah, 0x56 - int 0x21 - pop di + or ebx, 0x210000 + callf (interrupt_ptr) + pop edi + pop esi jmp .sys_zret diff --git a/plat/msdos386/libsys/sys_exists.s b/plat/msdos386/libsys/sys_exists.s index 8786f4c2a..f57d28b3e 100644 --- a/plat/msdos386/libsys/sys_exists.s +++ b/plat/msdos386/libsys/sys_exists.s @@ -16,11 +16,10 @@ .define __sys_exists __sys_exists: - int 3 - mov bx, sp - mov dx, 2(bx) - mov ax, 0x4300 + mov ebx, esp + mov edx, 4(ebx) + mov eax, 0x4300 int 0x21 - sbb ax, ax - inc ax + sbb eax, eax + inc eax ret diff --git a/plat/msdos386/libsys/sys_getdate.s b/plat/msdos386/libsys/sys_getdate.s index eeb118923..981253b93 100644 --- a/plat/msdos386/libsys/sys_getdate.s +++ b/plat/msdos386/libsys/sys_getdate.s @@ -16,11 +16,10 @@ .define __sys_getdate __sys_getdate: - int 3 movb ah, 0x2a int 0x21 - mov bx, sp - mov bx, 2(bx) - mov (bx), dx - mov 2(bx), cx + mov ebx, esp + mov ebx, 4(ebx) + o16 mov 0(ebx), dx + o16 mov 2(ebx), cx ret diff --git a/plat/msdos386/libsys/sys_gettime.s b/plat/msdos386/libsys/sys_gettime.s index d3ea65847..a565ea860 100644 --- a/plat/msdos386/libsys/sys_gettime.s +++ b/plat/msdos386/libsys/sys_gettime.s @@ -16,11 +16,10 @@ .define __sys_gettime __sys_gettime: - int 3 movb ah, 0x2c int 0x21 - mov bx, sp - mov bx, 2(bx) - mov (bx), cx - mov 2(bx), dx + mov ebx, esp + mov ebx, 2(ebx) + o16 mov 0(ebx), cx + o16 mov 2(ebx), dx ret diff --git a/plat/msdos386/libsys/sys_isopen.s b/plat/msdos386/libsys/sys_isopen.s index 5da95a44e..5a5fed07c 100644 --- a/plat/msdos386/libsys/sys_isopen.s +++ b/plat/msdos386/libsys/sys_isopen.s @@ -17,11 +17,10 @@ .define __sys_isopen __sys_isopen: - int 3 - mov bx, sp - mov bx, 2(bx) - mov ax, 0x4400 + mov ebx, esp + mov ebx, 4(bx) + mov eax, 0x4400 int 0x21 - sbb ax, ax - inc ax + sbb eax, eax + inc eax ret diff --git a/plat/msdos386/libsys/sys_isreadyr.s b/plat/msdos386/libsys/sys_isreadyr.s index ff3960b27..9a646adc8 100644 --- a/plat/msdos386/libsys/sys_isreadyr.s +++ b/plat/msdos386/libsys/sys_isreadyr.s @@ -17,13 +17,13 @@ .define __sys_isreadyr __sys_isreadyr: - mov ebx, sp + mov ebx, esp mov eax, 0x4406 mov ebx, 4(ebx) int 0x21 jnc ok movb al, 0 ok: - cbw - cwd + o16 cbw + cwde ret diff --git a/plat/msdos386/libsys/sys_rawcreat.s b/plat/msdos386/libsys/sys_rawcreat.s index 0d765a27d..b15df3f4f 100644 --- a/plat/msdos386/libsys/sys_rawcreat.s +++ b/plat/msdos386/libsys/sys_rawcreat.s @@ -16,10 +16,30 @@ .define __sys_rawcreat __sys_rawcreat: - int 3 + ! Copy filename to transfer buffer. + + mov ebx, esp + push esi + push edi + mov esi, 4(ebx) + movzx edi, (transfer_buffer_ptr) + mov es, (pmode_ds) + cld +1: + lodsb + stosb + testb al, al + jnz 1b + + ! Make the DOS call. + movb ah, 0x3c - mov bx, sp - mov dx, 2(bx) - mov cx, 4(bx) - int 0x21 + movzx edx, (transfer_buffer_ptr) + movb al, 8(ebx) + or ebx, 0x210000 + callf (interrupt_ptr) + + pop edi + pop esi jmp .sys_axret + diff --git a/plat/msdos386/libsys/sys_rawlseek.s b/plat/msdos386/libsys/sys_rawlseek.s index 06a7783a7..c38a1e0b1 100644 --- a/plat/msdos386/libsys/sys_rawlseek.s +++ b/plat/msdos386/libsys/sys_rawlseek.s @@ -16,12 +16,11 @@ .define __sys_rawlseek __sys_rawlseek: - int 3 movb ah, 0x42 - mov bx, sp - mov dx, 4(bx) - mov cx, 6(bx) - movb al, 8(bx) - mov bx, 2(bx) + mov ebx, esp + mov edx, 8(bx) + mov ecx, 12(bx) + movb al, 16(bx) + mov ebx, 4(bx) int 0x21 jmp .sys_dxaxret diff --git a/plat/msdos386/libsys/sys_rawopen.s b/plat/msdos386/libsys/sys_rawopen.s index 5fae1bba4..bb4ff5acb 100644 --- a/plat/msdos386/libsys/sys_rawopen.s +++ b/plat/msdos386/libsys/sys_rawopen.s @@ -16,10 +16,30 @@ .define __sys_rawopen __sys_rawopen: - int 3 + ! Copy filename to transfer buffer. + + mov ebx, esp + push esi + push edi + + mov esi, 4(ebx) + movzx edi, (transfer_buffer_ptr) + mov es, (pmode_ds) + cld +1: + lodsb + stosb + testb al, al + jnz 1b + + ! Make the DOS call. + movb ah, 0x3d - mov bx, sp - mov dx, 2(bx) - movb al, 4(bx) - int 0x21 + o16 mov dx, (transfer_buffer_ptr) + movb al, 8(ebx) + or ebx, 0x210000 + callf (interrupt_ptr) + + pop edi + pop esi jmp .sys_axret diff --git a/plat/msdos386/libsys/sys_rawread.s b/plat/msdos386/libsys/sys_rawread.s index c54410347..f5b0c1a35 100644 --- a/plat/msdos386/libsys/sys_rawread.s +++ b/plat/msdos386/libsys/sys_rawread.s @@ -12,12 +12,6 @@ .sect .text -.extern pmode_ds -.extern pmode_cs -.extern rmode -.extern transfer_buffer_ptr -.extern interrupt_ptr - ! Read bytes from a file descriptor. These routines do not do any ! translation between CRLF and LF line endings. ! @@ -27,6 +21,8 @@ .define __sys_rawread __sys_rawread: enter 0, 0 + push esi + push edi file_handle = 2*4 write_buffer = 3*4 amount_to_read = 4*4 @@ -43,7 +39,6 @@ amount_to_read = 4*4 movb ah, 0x3f o16 mov dx, (transfer_buffer_ptr) o16 mov bx, file_handle(ebp) - mov ecx, 0x80 or ebx, 0x210000 callf (interrupt_ptr) jnc success @@ -52,8 +47,8 @@ amount_to_read = 4*4 push eax call __sys_seterrno - leave - ret + pop ecx + jmp exit success: ! Copy eax bytes out of the transfer buffer. @@ -71,6 +66,9 @@ success: loop 1b pop eax +exit: + pop edi + pop esi leave ret diff --git a/plat/msdos386/libsys/sys_rawwrite.s b/plat/msdos386/libsys/sys_rawwrite.s index 5451670fe..3ac3a7e16 100644 --- a/plat/msdos386/libsys/sys_rawwrite.s +++ b/plat/msdos386/libsys/sys_rawwrite.s @@ -12,12 +12,6 @@ .sect .text -.extern pmode_ds -.extern pmode_cs -.extern rmode -.extern transfer_buffer_ptr -.extern interrupt_ptr - ! Write bytes to/to a file descriptor. These routines do not do any ! translation between CRLF and LF line endings. ! @@ -27,6 +21,8 @@ .define __sys_rawwrite __sys_rawwrite: enter 0, 0 + push esi + push edi file_handle = 2*4 read_buffer = 3*4 amount_to_write = 4*4 @@ -59,7 +55,10 @@ amount_to_write = 4*4 push eax call __sys_seterrno + pop ecx exit: + pop edi + pop esi leave ret diff --git a/plat/msdos386/libsys/unlink.s b/plat/msdos386/libsys/unlink.s index 912f6958d..7d023ad48 100644 --- a/plat/msdos386/libsys/unlink.s +++ b/plat/msdos386/libsys/unlink.s @@ -16,8 +16,29 @@ .define _unlink _unlink: - mov bx, sp - mov dx, 2(bx) + ! Copy filename to transfer buffer. + + mov ebx, esp + push esi + push edi + + mov esi, 4(ebx) + movzx edi, (transfer_buffer_ptr) + mov es, (pmode_ds) + cld +1: + lodsb + stosb + testb al, al + jnz 1b + + ! Make the DOS call. + + movzx edi, (transfer_buffer_ptr) movb ah, 0x41 - int 0x21 + or ebx, 0x210000 + callf (interrupt_ptr) + + pop edi + pop esi jmp .sys_zret diff --git a/plat/msdos386/stub.s b/plat/msdos386/stub.s index 35b9e8e40..219d66470 100644 --- a/plat/msdos386/stub.s +++ b/plat/msdos386/stub.s @@ -321,24 +321,21 @@ interrupt: mov (dpmi_ds), ax mov (dpmi_ss), ax push es - push ds - mov ax, dosstack ! auto stack is too small - mov (dpmi_sp), ax + mov (dpmi_sp), dosstack ! auto stack is too small push ds pop es - mov di, dpmi_edi + o32 mov edi, dpmi_edi mov ax, 0x300 o32 shr ebx, 16 int 0x31 ! simulate DOS interrupt - pop ds pop es - pushf o32 movzx eax, (dpmi_eax) o32 movzx ebx, (dpmi_ebx) o32 movzx ecx, (dpmi_ecx) o32 movzx edx, (dpmi_edx) o32 movzx esi, (dpmi_esi) o32 movzx edi, (dpmi_edi) + push (dpmi_flags) popf ret From c37c0e62cc31d181defb7a4043f81c73fbbcd87c Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 19 Aug 2022 20:03:40 +0200 Subject: [PATCH 18/20] Remember to actually update the brk position when calling brk. --- plat/msdos386/libsys/sbrk.c | 1 + 1 file changed, 1 insertion(+) diff --git a/plat/msdos386/libsys/sbrk.c b/plat/msdos386/libsys/sbrk.c index 988d406f3..2dbd610f3 100644 --- a/plat/msdos386/libsys/sbrk.c +++ b/plat/msdos386/libsys/sbrk.c @@ -31,6 +31,7 @@ void* sbrk(int increment) if (brk(new) < 0) goto out_of_memory; + current = new; return old; out_of_memory: From d24c3f8722b7d6a82cddd99d747d3531ffd2a27c Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 19 Aug 2022 20:03:48 +0200 Subject: [PATCH 19/20] Fix typo. --- plat/msdos386/libsys/sys_gettime.s | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plat/msdos386/libsys/sys_gettime.s b/plat/msdos386/libsys/sys_gettime.s index a565ea860..733ad58ac 100644 --- a/plat/msdos386/libsys/sys_gettime.s +++ b/plat/msdos386/libsys/sys_gettime.s @@ -16,10 +16,11 @@ .define __sys_gettime __sys_gettime: + int 3 movb ah, 0x2c int 0x21 mov ebx, esp - mov ebx, 2(ebx) + mov ebx, 4(ebx) o16 mov 0(ebx), cx o16 mov 2(ebx), dx ret From 887ec0656e91228cf6a3e446dc8f16b07914f9e8 Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 19 Aug 2022 20:08:39 +0200 Subject: [PATCH 20/20] Update documentation. --- README | 3 ++- plat/msdos386/README | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 plat/msdos386/README diff --git a/README b/README index 07903da95..5a305d6ab 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ =================================== © 1987-2005 Vrije Universiteit, Amsterdam - 2022-06-18 + 2022-08-19 INTRODUCTION @@ -38,6 +38,7 @@ cpm produces i80 CP/M .COM files rpi produces Raspberry Pi GPU binaries pdpv7 produces PDP/11 V7 Unix binaries msdos86 produces i86 MS-DOS .COM files +msdos386 produces i386 MS-DOS 32-bit DPMI .EXE files diff --git a/plat/msdos386/README b/plat/msdos386/README new file mode 100644 index 000000000..0a52528a6 --- /dev/null +++ b/plat/msdos386/README @@ -0,0 +1,24 @@ +The msdos386 platform +===================== + +msdos386 is an i386-based BSP that produces DPMI DOS executables. It should +have the same functionality as msdos86 (as the libc is all the same code), but +has been much less well tested. + +The code runs in flat 32-bit mode, so normal 32-bit pointers work with no +worries about segmentation. It requires a DPMI host to run; it was tested with +CWSDPMI. It will _not_ automatically load the host --- you need to manually +install the DPMI hsot first. + +IEEE floating point is available, but requires an FPU. + + +Example command line +==================== + +ack -mmsdos386 -O -o msdos386.exe examples/paranoia.c + + +David Given +dg@cowlark.com +