Adding MS-DOS .com program support (msdos86). Still incomplete.
This commit is contained in:
		
							parent
							
								
									3dcd16e0a0
								
							
						
					
					
						commit
						4c678ca210
					
				
					 6 changed files with 390 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -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…
	
	Add table
		
		Reference in a new issue