fpc/rtl/win16/prt0comn.asm
nickysn 0034e53445 - removed the win16 tiny memory model startup code loader - 16-bit windows
simply doesn't support the tiny memory model

git-svn-id: trunk@31705 -
2015-09-15 19:48:04 +00:00

239 lines
7.3 KiB
NASM

; common startup code for all the memory models
%ifdef __TINY__
%fatal "The tiny memory model is not supported by Windows."
%elifdef __SMALL__
%define __NEAR_CODE__
%define __NEAR_DATA__
%elifdef __MEDIUM__
%define __FAR_CODE__
%define __NEAR_DATA__
%elifdef __COMPACT__
%define __NEAR_CODE__
%define __FAR_DATA__
%elifdef __LARGE__
%define __FAR_CODE__
%define __FAR_DATA__
%elifdef __HUGE__
%define __FAR_CODE__
%define __FAR_DATA__
%else
%fatal "Memory model not defined."
%endif
%ifdef __FAR_CODE__
extra_param_offset equ 2
%else
extra_param_offset equ 0
%endif
%ifdef __FAR_DATA__
extra_data_offset equ 2
%else
extra_data_offset equ 0
%endif
cpu 8086
segment _TEXT use16 class=CODE align=1
extern PASCALMAIN
extern __fpc_PrefixSeg
extern __fpc_CmdLine
extern __fpc_CmdShow
extern __fpc_HInstance
extern __fpc_HPrevInst
extern __fpc_SelectorInc
extern ___stack
extern InitTask
import InitTask KERNEL
extern WaitEvent
import WaitEvent KERNEL
extern InitApp
import InitApp USER
extern __AHIncr
import __AHIncr KERNEL
..start: ; Win16 applications start with the following
; values in registers:
;
; AX = zero
; BX = the size, in bytes, of the stack
; CX = the size, in bytes, of the heap
; DI = handle, identifying the new application instance
; SI = handle, identifying the previous application instance
; BP = zero
; ES = segment of the Program Segment Prefix (PSP)
; DS = segment of the automatic data segment for the application
; SS = DS
; SP = offset of the first byte of the application stack
; call InitTask to initialize the task. Windows expects this to
; be the first function, called by the application code. On entry,
; it expects all the startup parameters in registers described above.
call far InitTask
; InitTask result:
; AX = 1-success; 0-error
test ax, ax
jz error
; InitTask result:
; CX = stack limit, in bytes
; DI = instance handle for the new task
; DX = the nCmdShow parameter
; ES = segment of the Program Segment Prefix (PSP) for the new task
; ES:BX = the command line
; SI = instance handle for the previous application instance (if any)
mov ax, es
mov [__fpc_PrefixSeg], ax
mov [__fpc_CmdLine+2], ax
mov [__fpc_CmdLine], bx
mov [__fpc_CmdShow], dx
mov [__fpc_HInstance], di
mov [__fpc_HPrevInst], si
; the offset of the Win16 kernel function __AHIncr (by definition)
; gives us the value of SelectorInc. The function __AHIncr is
; otherwise useless (when called, it increments AH by one :) )
; The value of SelectorInc is usually 8 in most (all?) win16
; implementations, but it's good practice not to hardcode it.
mov word [__fpc_SelectorInc], __AHIncr
; call WaitEvent(0) to clear the event that started this task
; Windows expects this call immediately after InitTask
xor ax, ax
push ax
call far WaitEvent
; call InitApp(hInstance) to initialize the queue and support
; routines for the app. Windows expects this to be the third
; call in the Win16 startup sequence.
push word [__fpc_HInstance]
call far InitApp
test ax, ax
jz error
%ifdef __FAR_CODE__
call far PASCALMAIN
%else
call PASCALMAIN
%endif
error:
mov ax, 4cffh
int 21h
global FPC_MSDOS_CARRY
FPC_MSDOS_CARRY:
stc
global FPC_MSDOS
FPC_MSDOS:
mov al, 21h ; not ax, because only the low byte is used
pop dx
%ifdef __FAR_CODE__
pop bx
%endif
pop cx
%ifdef __FAR_DATA__
pop si
%endif
push ax
%ifdef __FAR_DATA__
push si
%endif
push cx
%ifdef __FAR_CODE__
push bx
%endif
push dx
; global FPC_INTR
;FPC_INTR:
%ifdef __FAR_CODE__
inc bp
%endif
push bp
mov bp, sp
mov al, byte [bp + 6 + extra_param_offset + extra_data_offset]
; mov byte [cs:int_number], al
mov si, [bp + 4 + extra_param_offset]
push ds
%ifdef __FAR_DATA__
mov ax, [bp + 6 + extra_param_offset]
mov ds, ax
%endif
mov ax, word [si + 16]
mov es, ax
mov ax, word [si + 14] ; ds
push ax
mov ax, word [si]
mov bx, word [si + 2]
mov cx, word [si + 4]
mov dx, word [si + 6]
mov bp, word [si + 8]
mov di, word [si + 12]
mov si, word [si + 10]
pop ds
; db 0CDh ; opcode of INT xx
;int_number:
; db 255
int 21h
pushf
push ds
push si
push bp
mov bp, sp
%ifdef __FAR_DATA__
mov si, [bp + 16 + extra_param_offset]
%else
mov si, word [bp + 8]
%endif
mov ds, si
mov si, word [bp + 14 + extra_param_offset]
mov word [si], ax
mov word [si + 2], bx
mov word [si + 4], cx
mov word [si + 6], dx
mov word [si + 12], di
mov ax, es
mov word [si + 16], ax
pop ax
mov word [si + 8], ax
pop ax
mov word [si + 10], ax
pop ax
mov word [si + 14], ax
pop ax
mov word [si + 18], ax
pop ds
pop bp
%ifdef __FAR_CODE__
dec bp
retf 4 + extra_data_offset
%else
ret 4 + extra_data_offset
%endif
segment _DATA use16 class=DATA align=2
; the first 16 bytes of the automatic data segment are reserved.
; they are filled by the InitTask function with these values
dw 0
oOldSP: dw 0
hOldSS: dw 5
pLocalHeap: dw 0
pAtomTable: dw 0
pStackTop: dw 0
pStackMin: dw 0
pStackBot: dw 0
; end of reserved area, filled by InitTask
segment stack stack class=STACK align=16
group DGROUP _DATA stack