236 lines
4.8 KiB
ArmAsm
236 lines
4.8 KiB
ArmAsm
#
|
|
! $Source$
|
|
! $State$
|
|
! $Revision$
|
|
|
|
! Declare segments (the order is important).
|
|
|
|
.sect .text
|
|
.sect .rom
|
|
.sect .data
|
|
.sect .bss
|
|
|
|
.sect .text
|
|
#define STACK_BUFFER 128 /* number of bytes to leave for stack */
|
|
|
|
! g 18b to break at the retf before coming here
|
|
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.
|
|
!
|
|
! ax: pmode code segment of stub
|
|
! 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)
|
|
|
|
! Clear BSS.
|
|
|
|
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
|
|
mov es, 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 esi, bx
|
|
shl esi, 4 ! convert to linear address
|
|
|
|
! 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
|
|
jz 2f ! empty environment
|
|
1:
|
|
repnz scasb
|
|
inc edx
|
|
scasb
|
|
jnz 1b
|
|
2:
|
|
add edi, 2 ! skip the mysterious word
|
|
repnz scasb ! program name
|
|
|
|
! 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
|
|
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 esp, 3*4
|
|
mov eax, esp
|
|
|
|
! Build up argc, argv[], and envp[].
|
|
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 esp, 5*4
|
|
|
|
! 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
|
|
|
|
! 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.)
|
|
|
|
.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
|
|
|
|
.comm .doshandle, 2
|
|
.comm _psp, 256
|
|
|
|
.sect .bss
|
|
.space 32*1024
|
|
.stack:
|
|
|
|
! vim: ts=4 sw=4 et ft=asm
|
|
|