plat/msdos86: free up program memory above 64 KiB; also check

we have enough memory for BSS
This commit is contained in:
tkchia 2022-06-28 20:13:16 +00:00
parent df6cfe0410
commit 1c71653d7f
2 changed files with 41 additions and 17 deletions

View file

@ -12,6 +12,8 @@
.sect .text .sect .text
#define STACK_BUFFER 128 /* number of bytes to leave for stack */
begtext: begtext:
! Make sure we are running under MS-DOS 2 or above. ! Make sure we are running under MS-DOS 2 or above.
! !
@ -20,9 +22,38 @@ begtext:
! segment. (DOS 3+ does; DOS 2.x does not.) ! segment. (DOS 3+ does; DOS 2.x does not.)
movb ah, 0x30 movb ah, 0x30
int 0x21 int 0x21
cbw
cmpb al, 2 cmpb al, 2
xchg bx, ax xchg bp, ax
jc bad_sys 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. ! Clear BSS.
mov di, begbss mov di, begbss
@ -35,11 +66,12 @@ begtext:
! Get the size of the environment variables plus (if present) the ! Get the size of the environment variables plus (if present) the
! program name. Also count the number of environment variables. ! program name. Also count the number of environment variables.
mov es, (0x002C)
xor di, di xor di, di
mov es, 0x002C(di)
! ax = 0 from above ! ax = 0 from above
cwd ! dx = count of env. vars. cwd ! dx = count of env. vars.
mov cx, -1 ! cx = 0 from above
dec cx ! cx = max. str. bytes to scan
scasb ! handle special case of empty env. scasb ! handle special case of empty env.
jz is_empty_env jz is_empty_env
size_env: size_env:
@ -48,7 +80,7 @@ size_env:
scasb scasb
jnz size_env jnz size_env
is_empty_env: is_empty_env:
cmpb bl, 2 cmp bp, 2
jz no_argv0 jz no_argv0
scasw scasw
repnz scasb repnz scasb
@ -58,10 +90,9 @@ no_argv0:
! onto the stack. ! onto the stack.
mov si, di mov si, di
dec si dec si
and si, -2
std std
copy_env: copy_env:
test si, si and si, -2
eseg lodsw eseg lodsw
push ax push ax
jnz copy_env jnz copy_env
@ -79,7 +110,7 @@ copy_env:
! Build up argc, argv[], and envp[]. ! Build up argc, argv[], and envp[].
push ax ! output buffer for argc, argv, envp push ax ! output buffer for argc, argv, envp
push bx ! MS-DOS version push bp ! MS-DOS version
push cx ! env. string data push cx ! env. string data
push dx ! count of env. vars. push dx ! count of env. vars.
mov ax, 0x0080 mov ax, 0x0080
@ -97,13 +128,6 @@ copy_env:
push ax push ax
call _exit call _exit
bad_sys:
mov dx, bad_sys_msg
dos_msg:
movb ah, 9
int 0x21
ret
no_room: no_room:
mov dx, no_room_msg mov dx, no_room_msg
call dos_msg call dos_msg

View file

@ -22,7 +22,7 @@ struct for_main {
* Return zero if everything went well, non-zero otherwise. * Return zero if everything went well, non-zero otherwise.
*/ */
int _sys_initmain(char *arg_data, size_t n_env_vars, char *env_data, int _sys_initmain(char *arg_data, size_t n_env_vars, char *env_data,
unsigned msdos_ver, struct for_main *out) unsigned msdos_ver_major, struct for_main *out)
{ {
char **argv, **envp; char **argv, **envp;
char c, *p, **pp; char c, *p, **pp;
@ -100,7 +100,7 @@ int _sys_initmain(char *arg_data, size_t n_env_vars, char *env_data,
* shortword) following the environment variables, so advance p by 3 * shortword) following the environment variables, so advance p by 3
* bytes to get at the program name. * bytes to get at the program name.
*/ */
if ((msdos_ver & 0x00ff) >= 3) if (msdos_ver_major >= 3)
{ {
p += 3; p += 3;
argv[0] = p; argv[0] = p;