Adding MS-DOS .com program support (msdos86). Still incomplete.
This commit is contained in:
parent
3dcd16e0a0
commit
4c678ca210
|
@ -11,6 +11,7 @@ vars.plats = {
|
|||
"linux68k",
|
||||
"linuxppc",
|
||||
"linuxmips",
|
||||
"msdos86",
|
||||
"osx386",
|
||||
"osxppc",
|
||||
"pc86",
|
||||
|
|
145
plat/msdos86/boot.s
Normal file
145
plat/msdos86/boot.s
Normal file
|
@ -0,0 +1,145 @@
|
|||
#
|
||||
! $Source$
|
||||
! $State$
|
||||
! $Revision$
|
||||
|
||||
! Declare segments (the order is important).
|
||||
|
||||
.sect .text
|
||||
.sect .rom
|
||||
.sect .data
|
||||
.sect .bss
|
||||
|
||||
.sect .text
|
||||
|
||||
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
|
||||
cmpb al, 2
|
||||
xchg bx, ax
|
||||
jc bad_sys
|
||||
|
||||
! 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.
|
||||
mov es, (0x002C)
|
||||
xor di, di
|
||||
! ax = 0 from above
|
||||
cwd ! dx = count of env. vars.
|
||||
mov cx, -1
|
||||
scasb ! handle special case of empty env.
|
||||
jz is_empty_env
|
||||
size_env:
|
||||
inc dx
|
||||
repnz scasb
|
||||
scasb
|
||||
jnz size_env
|
||||
is_empty_env:
|
||||
cmpb bl, 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
|
||||
and si, -2
|
||||
std
|
||||
copy_env:
|
||||
test si, si
|
||||
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 bx ! 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
|
||||
|
||||
bad_sys:
|
||||
mov dx, bad_sys_msg
|
||||
dos_msg:
|
||||
movb ah, 9
|
||||
int 0x21
|
||||
ret
|
||||
|
||||
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
|
25
plat/msdos86/build-pkg.lua
Normal file
25
plat/msdos86/build-pkg.lua
Normal file
|
@ -0,0 +1,25 @@
|
|||
include("plat/build.lua")
|
||||
|
||||
ackfile {
|
||||
name = "boot",
|
||||
srcs = { "./boot.s" },
|
||||
vars = { plat = "msdos86" }
|
||||
}
|
||||
|
||||
build_plat_libs {
|
||||
name = "libs",
|
||||
arch = "i86",
|
||||
plat = "msdos86",
|
||||
}
|
||||
|
||||
installable {
|
||||
name = "pkg",
|
||||
map = {
|
||||
"+tools",
|
||||
"+libs",
|
||||
"./include+pkg",
|
||||
["$(PLATIND)/msdos86/boot.o"] = "+boot",
|
||||
["$(PLATIND)/msdos86/libsys.a"] = "./libsys+lib",
|
||||
}
|
||||
}
|
||||
|
21
plat/msdos86/build-tools.lua
Normal file
21
plat/msdos86/build-tools.lua
Normal file
|
@ -0,0 +1,21 @@
|
|||
include("plat/build.lua")
|
||||
|
||||
build_as {
|
||||
name = "as",
|
||||
arch = "i86",
|
||||
}
|
||||
|
||||
build_ncg {
|
||||
name = "ncg",
|
||||
arch = "i86",
|
||||
}
|
||||
|
||||
return installable {
|
||||
name = "tools",
|
||||
map = {
|
||||
["$(PLATDEP)/msdos86/as"] = "+as",
|
||||
["$(PLATDEP)/msdos86/ncg"] = "+ncg",
|
||||
["$(PLATIND)/descr/msdos86"] = "./descr",
|
||||
"util/opt+pkg",
|
||||
}
|
||||
}
|
86
plat/msdos86/descr
Normal file
86
plat/msdos86/descr
Normal file
|
@ -0,0 +1,86 @@
|
|||
# $Source$
|
||||
# $State$
|
||||
# $Revision$
|
||||
|
||||
var w=2
|
||||
var wa=2
|
||||
var p=2
|
||||
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=i86
|
||||
var PLATFORM=msdos86
|
||||
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
|
||||
|
||||
# These will be overridden under the small (separate I/D) memory model.
|
||||
|
||||
var SEPID=-b0:0x100
|
||||
var LOD=aslod
|
||||
|
||||
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 -i SEPID=-b1:0
|
||||
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}/libend.a)
|
||||
linker
|
||||
end
|
||||
name cv
|
||||
from .out
|
||||
to .exe
|
||||
mapflag -i LOD=amzlod
|
||||
program {EM}/bin/{LOD}
|
||||
args < >
|
||||
outfile msdos86.exe
|
||||
end
|
112
plat/msdos86/libsys/sys_initmain.c
Normal file
112
plat/msdos86/libsys/sys_initmain.c
Normal file
|
@ -0,0 +1,112 @@
|
|||
/* $Source$
|
||||
* $State$
|
||||
* $Revision$
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define OUT_OF_MEMORY (void*)(-1) /* sbrk returns this on failure */
|
||||
|
||||
struct for_main {
|
||||
int argc;
|
||||
char **argv;
|
||||
char **envp;
|
||||
};
|
||||
|
||||
/*
|
||||
* Marshal the command line and environment variable data provided by
|
||||
* MS-DOS, into the standard format expected by a C main(...) routine. The
|
||||
* environment variable data has been copied to the near data segment.
|
||||
*
|
||||
* Return zero if everything went well, non-zero otherwise.
|
||||
*/
|
||||
int _sys_initmain(char *arg_data, size_t n_env_vars, char *env_data,
|
||||
unsigned msdos_ver, struct for_main *out)
|
||||
{
|
||||
char **argv, **envp;
|
||||
char c, *p, **pp;
|
||||
unsigned char n;
|
||||
|
||||
/*
|
||||
* Allocate space for argv[] for the maximum possible number of
|
||||
* arguments. We can shrink this later.
|
||||
*/
|
||||
if ((argv = sbrk(65 * sizeof(char *))) == OUT_OF_MEMORY)
|
||||
return -1;
|
||||
out->argv = argv;
|
||||
|
||||
/* Sanity-check the original command line. */
|
||||
p = arg_data;
|
||||
n = (unsigned char)*p;
|
||||
if (n > 0x7E || p[1 + n] != '\r')
|
||||
return -1;
|
||||
|
||||
/* Initialize argv[0] to an empty string first. */
|
||||
*p = 0;
|
||||
argv[0] = p;
|
||||
|
||||
/*
|
||||
* Split the command line string into separate arguments.
|
||||
* TODO: handle double-quoting, backslashes, etc.
|
||||
*/
|
||||
pp = argv + 1;
|
||||
do
|
||||
{
|
||||
do
|
||||
c = *++p;
|
||||
while (c == ' ' || c == '\t');
|
||||
|
||||
if (c != '\r')
|
||||
{
|
||||
*pp++ = p;
|
||||
do
|
||||
c = *++p;
|
||||
while (c != ' ' && c != '\t' && c != '\r');
|
||||
*p = 0;
|
||||
}
|
||||
} while (c != '\r');
|
||||
|
||||
/* Wrap up argv[]. Compute argc. Free up unneeded space. */
|
||||
out->argc = pp - argv;
|
||||
*pp++ = NULL;
|
||||
if (brk(pp) != 0)
|
||||
return -1;
|
||||
|
||||
/* Allocate space for envp[]. */
|
||||
if ((envp = sbrk((n_env_vars + 1) * sizeof(char *))) == OUT_OF_MEMORY)
|
||||
return -1;
|
||||
out->envp = envp;
|
||||
|
||||
/*
|
||||
* Populate envp[]. The environment data is simply a series of ASCIIZ
|
||||
* strings, one after another, terminated by an empty string.
|
||||
*/
|
||||
pp = envp;
|
||||
p = env_data;
|
||||
while (*p)
|
||||
{
|
||||
*pp++ = p;
|
||||
while (*++p);
|
||||
++p;
|
||||
}
|
||||
*pp = NULL;
|
||||
|
||||
/*
|
||||
* If there is a program name (MS-DOS version is 3 or above), point
|
||||
* argv[0] to it.
|
||||
*
|
||||
* p points to the zero byte just before the count of strings (a
|
||||
* shortword) following the environment variables, so advance p by 3
|
||||
* bytes to get at the program name.
|
||||
*/
|
||||
if ((msdos_ver & 0x00ff) >= 3)
|
||||
{
|
||||
p += 3;
|
||||
argv[0] = p;
|
||||
}
|
||||
|
||||
/* We are done. */
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue