mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-07 20:08:12 +02:00
939 lines
28 KiB
ActionScript
939 lines
28 KiB
ActionScript
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
|
|
/*****************************************************************************\
|
|
* Interface to 32-bit executable (from stub.asm)
|
|
*
|
|
* cs:eip according to COFF header
|
|
* ds 32-bit data segment for COFF program
|
|
* fs selector for our data segment (fs:0 is stubinfo)
|
|
* ss:sp our stack (ss to be freed)
|
|
* <others> All unspecified registers have unspecified values in them.
|
|
\*****************************************************************************/
|
|
/* modified by Pierre Muller to become the prt0.s for FPC Pascal */
|
|
|
|
.file "v2prt0.as"
|
|
|
|
/* #include "stubinfo.h" */
|
|
STUBINFO = 0
|
|
STUBINFO_MAGIC = 0
|
|
STUBINFO_SIZE = 0x10
|
|
STUBINFO_MINSTACK = 0x14
|
|
STUBINFO_MEMORY_HANDLE = 0x18
|
|
STUBINFO_INITIAL_SIZE = 0x1c
|
|
STUBINFO_MINKEEP = 0x20
|
|
STUBINFO_DS_SELECTOR = 0x22
|
|
STUBINFO_DS_SEGMENT = 0x24
|
|
STUBINFO_PSP_SELECTOR = 0x26
|
|
STUBINFO_CS_SELECTOR = 0x28
|
|
STUBINFO_ENV_SIZE = 0x2a
|
|
STUBINFO_BASENAME = 0x2c
|
|
STUBINFO_ARGV0 = 0x34
|
|
STUBINFO_DPMI_SERVER = 0x44
|
|
STUBINFO_END = 0x54
|
|
|
|
|
|
/* .comm __stklen, 4
|
|
this is added to the compiler so that we can specify
|
|
the stack size */
|
|
.comm __stkbottom,4
|
|
.comm __stubinfo, 4
|
|
.comm ___djgpp_base_address, 4
|
|
.comm ___djgpp_selector_limit, 4
|
|
.comm __crt0_startup_flags, 4
|
|
.comm ___djgpp_stack_limit, 4
|
|
.lcomm sel_buf, 8
|
|
|
|
/* ___djgpp_ds_alias defined in go32/exceptn.s */
|
|
/* inserted at the end of this file */
|
|
/* we use a local copy that will be copied to exceptn.s */
|
|
.globl ___v2prt0_ds_alias
|
|
___v2prt0_ds_alias:
|
|
.long 0
|
|
/* allocate 32*4 bytes for RMCB under the $ffff limit for Windows NT */
|
|
.globl ___v2prt0_rmcb_regs
|
|
___v2prt0_rmcb_regs:
|
|
.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
.data
|
|
|
|
___djgpp_memory_handle_pointer:
|
|
.long ___djgpp_memory_handle_list+8 /* Next free, first for stub */
|
|
.comm ___djgpp_memory_handle_list, 2048 /* Enough for 256 handles */
|
|
|
|
/* simply get current state */
|
|
___sbrk_interrupt_state:
|
|
.long 0x902
|
|
|
|
sbrk16_first_byte:
|
|
.include "sbrk16.ah"
|
|
sbrk16_last_byte:
|
|
|
|
sbrk16_api_ofs:
|
|
.long 0
|
|
sbrk16_api_seg:
|
|
.word 0
|
|
zero:
|
|
.long 0
|
|
|
|
exit16_first_byte:
|
|
.include "exit16.ah"
|
|
exit16_last_byte:
|
|
|
|
/* hook_387_emulator:
|
|
.long ___emu387_load_hook */
|
|
|
|
/* this is for when main comes from a library */
|
|
.long _main
|
|
|
|
|
|
.text
|
|
.globl start
|
|
start:
|
|
pushl %ds /* set %es same as %ds */
|
|
popl %es /* push/pop 4 bytes shorter than ax */
|
|
|
|
/* Enable NULL pointer protection if DPMI supports it */
|
|
testb $0x1, __crt0_startup_flags+1 /* include/crt0.h */
|
|
jnz 1f
|
|
movl $start, %eax
|
|
cmpl $0x1000, %eax
|
|
jl 1f
|
|
movw $0x507, %ax
|
|
.byte 0x64 /* fs: */
|
|
movl STUBINFO_MEMORY_HANDLE, %esi
|
|
xorl %ebx, %ebx /* Offset 0 in mem block */
|
|
movl $1, %ecx /* Set one page */
|
|
movl $zero, %edx
|
|
int $0x31 /* Make null page uncommitted */
|
|
jnc 1f
|
|
call v2prt0_windows
|
|
1:
|
|
/* Create an alias for DS to be used by real-mode callbacks (exception handler messes with DS itself) */
|
|
|
|
movw %ds, %bx
|
|
movw $0x000a, %ax
|
|
int $0x31
|
|
jnc .Lds_alias_ok
|
|
movb $0x4c, %ah
|
|
int $0x21
|
|
|
|
.Lds_alias_ok:
|
|
movw %ax, ___v2prt0_ds_alias
|
|
movl %eax, %ebx
|
|
movw $0x0009, %ax
|
|
movw %cs, %cx /* get CPL from %cs */
|
|
andl $3, %ecx
|
|
shll $5, %ecx /* move it into place */
|
|
orw $0xc093, %cx
|
|
int $0x31 /* set access rights for alias */
|
|
|
|
/* Maybe set our DS limit to 4Gb in size if flag set */
|
|
testb $0x80, __crt0_startup_flags /* include/crt0.h */
|
|
jz 2f
|
|
movw $0xffff, %cx
|
|
movl %ecx, %edx
|
|
movw $0x0008, %ax /* reset alias limit to -1 */
|
|
int $0x31
|
|
movw %cs, %bx
|
|
movw $0x0008, %ax /* reset DS limit to -1 */
|
|
int $0x31
|
|
movw %ds, %bx
|
|
movw $0x0008, %ax /* reset DS limit to -1 */
|
|
int $0x31
|
|
lsl %ebx, %ebx /* Should be -1 */
|
|
incl %ebx
|
|
jz 2f
|
|
andb $0x7f, __crt0_startup_flags /* clear it if failure */
|
|
2:
|
|
/* Allocate some DOS memory and copy our sbrk helper into it. */
|
|
movl $sbrk16_first_byte, %esi
|
|
movzwl 8(%esi), %ebx
|
|
shrl $4, %ebx
|
|
movw $0x0100, %ax
|
|
int $0x31
|
|
jnc .Ldos_alloc_ok
|
|
movb $0x4c, %ah
|
|
int $0x21
|
|
|
|
.Ldos_alloc_ok:
|
|
movw %cs, 2(%esi)
|
|
/* store API information */
|
|
movw %ds, 4(%esi)
|
|
movw %dx, 6(%esi)
|
|
/* selector for allocated block */
|
|
|
|
movzwl (%esi), %eax /* calculate API address */
|
|
movl %eax, sbrk16_api_ofs
|
|
|
|
pushl %es /* move the data */
|
|
movw %dx, %es
|
|
movl $(sbrk16_last_byte - sbrk16_first_byte), %ecx
|
|
shrl $2,%ecx
|
|
xorl %edi, %edi
|
|
cld
|
|
rep
|
|
movsl
|
|
popl %es
|
|
|
|
movl %edx, %ebx /* dos memory selector */
|
|
movw $0x000b, %ax /* get descriptor */
|
|
movl $sel_buf, %edi
|
|
int $0x31
|
|
|
|
andb $0xbf, sel_buf+6 /* make 16-bit */
|
|
andb $0xf0, sel_buf+5 /* remove old type */
|
|
orb $0x0a, sel_buf+5 /* set new type to code/read */
|
|
|
|
xorl %eax, %eax /* allocate new selector */
|
|
movw $0x0001, %cx
|
|
int $0x31
|
|
movw %ax, sbrk16_api_seg
|
|
|
|
movl %eax, %ebx
|
|
movw $0x000c, %ax /* set descriptor */
|
|
movl $sel_buf, %edi
|
|
int $0x31
|
|
|
|
/* Initialize the brk/sbrk variables */
|
|
|
|
/* movl $end, __what_size_app_thinks_it_is */
|
|
.byte 0x64 /* fs: */
|
|
movl STUBINFO_INITIAL_SIZE, %eax
|
|
movl %eax, __what_size_dpmi_thinks_we_are
|
|
|
|
/* Maybe lock the initial block, expects BX:CX */
|
|
movl %ecx,%ebx
|
|
movl %edx,%ecx
|
|
addw $4096,%cx /* Skip null page */
|
|
adcl $0,%ebx
|
|
subl $4096,%eax
|
|
pushl %eax
|
|
call lock_memory
|
|
|
|
.byte 0x64 /* fs: */
|
|
movl STUBINFO_MEMORY_HANDLE, %eax
|
|
movl %eax, ___djgpp_memory_handle_list
|
|
|
|
.byte 0x64 /* fs: */ /* copy stubinfo into local memory */
|
|
movl STUBINFO_SIZE, %eax
|
|
pushl %eax
|
|
call ___sbrk
|
|
movl %eax, __stubinfo
|
|
movl %eax,operatingsystem_stub_info
|
|
movl %eax, %edi
|
|
.byte 0x64 /* fs: */
|
|
movl STUBINFO_SIZE, %ecx
|
|
shrl $2, %ecx
|
|
xorl %esi, %esi /* Zero */
|
|
pushl %ds
|
|
pushl %fs
|
|
popl %ds
|
|
cld
|
|
rep
|
|
movsl
|
|
popl %ds
|
|
movl __stklen, %eax /* get program-requested stack size */
|
|
.byte 0x64 /* fs: */
|
|
movl STUBINFO_MINSTACK, %ecx /* get stub-requested stack size */
|
|
cmpl %ecx, %eax
|
|
jge .Luse_stubinfo_stack_size /* use the larger of the two */
|
|
movl %ecx, %eax
|
|
movl %eax, __stklen /* store the actual stack length */
|
|
.Luse_stubinfo_stack_size:
|
|
pushl %eax
|
|
call ___sbrk /* allocate the memory */
|
|
cmpl $-1, %eax
|
|
je .Lno_memory
|
|
movl %eax, ___djgpp_stack_limit /* Bottom of stack */
|
|
addl $256,%eax
|
|
movl %eax,__stkbottom /* for stack checks */
|
|
/* movl %eax,operatingsystem_stackbottom */
|
|
/* StackBottom is
|
|
a ThrteadVar and can not be given a symbol with name,
|
|
copying value of __stkbottom to system.STackBottom variable
|
|
is done in system unit startup code. PM */
|
|
|
|
movl ___djgpp_stack_limit,%eax /* Bottom of stack */
|
|
addl __stklen, %eax
|
|
movw %ds, %dx /* set stack */
|
|
movw %dx, %ss
|
|
andl $0xfffffffc,%eax
|
|
movl %eax, %esp
|
|
|
|
xorl %ebp, %ebp
|
|
call ___prt1_startup /* run program */
|
|
jmp exit
|
|
|
|
.Lno_memory:
|
|
movb $0xff, %al
|
|
jmp exit
|
|
|
|
/*-----------------------------------------------------------------------------*/
|
|
|
|
/* #define FREESEL(x) movw x, %bx; movw $0x0001, %ax; int $0x31 */
|
|
.macro FREESEL x
|
|
movw \x,%bx
|
|
movw $0x0001,%ax
|
|
int $0x31
|
|
.endm
|
|
|
|
.global ___exit
|
|
.align 2
|
|
___exit:
|
|
/* special exit from dpmiexcp.c */
|
|
.global __exit
|
|
__exit:
|
|
movl 4(%esp),%eax
|
|
exit:
|
|
movl %eax,%ecx
|
|
xorl %eax,%eax
|
|
movw %ax,%fs
|
|
movw %ax,%gs
|
|
cmpl $0,_exception_exit
|
|
jz .Lno_exception
|
|
pushl %ecx
|
|
call *_exception_exit
|
|
popl %ecx
|
|
.Lno_exception:
|
|
cli /* Just in case they didn't unhook ints */
|
|
FREESEL operatingsystem_go32_info_block+26 /* selector for linear memory */
|
|
FREESEL ___v2prt0_ds_alias /* DS alias for rmcb exceptions */
|
|
FREESEL sbrk16_api_seg /* sbrk cs */
|
|
movw sbrk16_first_byte+6,%dx /* selector for allocated DOS mem */
|
|
movw $0x101, %ax
|
|
int $0x31 /* Free block and selector */
|
|
9:
|
|
movl __stubinfo, %edx
|
|
movl STUBINFO_CS_SELECTOR(%edx), %eax
|
|
movw %ax, sbrk16_api_seg
|
|
xorl %edi, %edi
|
|
movl %edi, sbrk16_api_ofs /* Offset is zero */
|
|
|
|
movw STUBINFO_DS_SELECTOR(%edx), %es
|
|
movb %cl, %dl /* Exit status */
|
|
movl $exit16_first_byte, %esi
|
|
movl $(exit16_last_byte - exit16_first_byte), %ecx
|
|
cld
|
|
rep
|
|
movsb
|
|
|
|
movw %es,%ax /* We will free stack! */
|
|
movw %ax,%ss
|
|
movl $0x400,%esp /* Transfer buffer >= 1024 bytes */
|
|
|
|
xorl %ebp, %ebp /* V1.10 bug fix */
|
|
movl ___djgpp_memory_handle_list, %edi
|
|
movl ___djgpp_memory_handle_list+2, %esi /* Skip word prefixes */
|
|
|
|
FREESEL %ds
|
|
movw %cs, %bx
|
|
/* Call exit procedure with BX=32-bit CS; SI+DI=32-bit handle; DL=exit status */
|
|
.byte 0x2e
|
|
ljmp sbrk16_api_ofs
|
|
|
|
/*-----------------------------------------------------------------------------*/
|
|
|
|
/* .lcomm __what_size_app_thinks_it_is, 4 */
|
|
__what_size_app_thinks_it_is:
|
|
.long end
|
|
.lcomm __what_we_return_to_app_as_old_size, 4
|
|
.lcomm __what_size_dpmi_thinks_we_are, 4
|
|
|
|
lock_memory:
|
|
/* BX:CX should be linear address; size is pushed on stack */
|
|
testb $0x10, __crt0_startup_flags+1 /* include/crt0.h */
|
|
jz 13f
|
|
pushl %esi
|
|
pushl %edi
|
|
pushl %eax
|
|
movl 16(%esp),%edi
|
|
movw 18(%esp),%si
|
|
movw $0x600,%ax
|
|
int $0x31
|
|
popl %eax
|
|
popl %edi
|
|
popl %esi
|
|
13: ret $4 /* Pop the argument */
|
|
|
|
|
|
.global ___sbrk
|
|
.align 2
|
|
___sbrk:
|
|
movl __what_size_app_thinks_it_is, %eax
|
|
movl 4(%esp), %ecx /* Increment size */
|
|
addl %ecx, %eax
|
|
jnc .Lbrk_common
|
|
/* Carry is only set if a negative increment or wrap happens. Negative
|
|
increment is semi-OK, wrap (only for multiple zone sbrk) isn't. */
|
|
test $0x80000000, %ecx /* Clears carry */
|
|
jnz .Lbrk_common
|
|
stc /* Put carry back */
|
|
jmp .Lbrk_common
|
|
|
|
.globl ___brk
|
|
.align 2
|
|
___brk:
|
|
movl 4(%esp), %eax
|
|
clc
|
|
|
|
.Lbrk_common:
|
|
pushl %esi
|
|
pushl %edi
|
|
pushl %ebx
|
|
|
|
movl __what_size_app_thinks_it_is, %edx /* save info */
|
|
movl %edx, __what_we_return_to_app_as_old_size
|
|
movl %eax, __what_size_app_thinks_it_is
|
|
|
|
/* multi code is not present */
|
|
/* jc 10f Wrap for multi-zone */
|
|
cmpl __what_size_dpmi_thinks_we_are, %eax /* don't bother shrinking */
|
|
jbe .Lbrk_nochange
|
|
|
|
addl $0x0000ffff, %eax /* round up to 64K block */
|
|
andl $0xffff0000, %eax
|
|
push %eax /* size - save for later */
|
|
|
|
movl ___djgpp_memory_handle_list, %edi /* request new size */
|
|
movw ___djgpp_memory_handle_list+2, %si
|
|
movl %eax, %ecx /* size not limit */
|
|
movl %eax, %ebx /* size not limit */
|
|
shrl $16, %ebx /* BX:CX size */
|
|
|
|
movw $0x0900, %ax /* disable interrupts */
|
|
int $0x31
|
|
movl %eax,___sbrk_interrupt_state
|
|
lcall sbrk16_api_ofs
|
|
setc %dl /* Save carry */
|
|
|
|
/* popl %eax restore interrupts
|
|
int $0x31 postponed after ds alias is set correctly */
|
|
|
|
test %dl,%dl
|
|
popl %edx
|
|
jne .Lbrk_error
|
|
|
|
movl %edi, ___djgpp_memory_handle_list /* store new handle */
|
|
movw %si, ___djgpp_memory_handle_list+2
|
|
movl %ecx, ___djgpp_base_address /* store new base address */
|
|
movw %bx, ___djgpp_base_address+2
|
|
|
|
movl %edx, %eax
|
|
movl __what_size_dpmi_thinks_we_are, %ecx
|
|
subl %ecx, %eax
|
|
|
|
addl ___djgpp_base_address, %ecx
|
|
movl %ecx, %ebx
|
|
shrl $16, %ebx /* BX:CX addr */
|
|
pushl %eax /* Size */
|
|
call lock_memory
|
|
|
|
decl %edx /* limit now, not size */
|
|
5: movl %edx, ___djgpp_selector_limit
|
|
orw $0x0fff, %dx /* low bits set */
|
|
movw $0x0008, %ax /* reset CS limit */
|
|
movw %cs, %bx
|
|
movl %edx, %ecx
|
|
shrl $16, %ecx
|
|
int $0x31 /* CX:DX is limit */
|
|
|
|
testb $0x80, __crt0_startup_flags /* include/crt0.h */
|
|
jnz 3f
|
|
movw $0x0008, %ax /* reset DS limit */
|
|
movw %ds, %bx
|
|
int $0x31
|
|
|
|
movw $0x0008, %ax /* reset DS alias limit */
|
|
movl ___v2prt0_ds_alias, %ebx
|
|
int $0x31
|
|
3:
|
|
movw $0x0007, %ax /* reset DS alias base */
|
|
movl ___v2prt0_ds_alias, %ebx
|
|
movl ___djgpp_base_address, %edx
|
|
movw ___djgpp_base_address+2, %cx
|
|
int $0x31
|
|
|
|
movl ___sbrk_interrupt_state,%eax /* restore interrupts */
|
|
int $0x31
|
|
movl ___djgpp_selector_limit, %edx
|
|
12: incl %edx /* Size not limit */
|
|
testb $0x60, __crt0_startup_flags /* include/crt0.h */
|
|
jz .Lno_fill_sbrk_memory
|
|
pushl %ds
|
|
popl %es
|
|
|
|
movl __what_size_dpmi_thinks_we_are, %edi /* set all newly resized bytes zero */
|
|
movl %edx, %ecx /* Limit */
|
|
subl %edi, %ecx /* Adjust count for base */
|
|
xorl %eax, %eax
|
|
testb $0x40, __crt0_startup_flags
|
|
jz .Lno_deadbeef
|
|
movl $0xdeadbeef, %eax /* something really easy to spot */
|
|
.Lno_deadbeef:
|
|
shrl $2, %ecx /* div 4 Longwords not bytes */
|
|
cld
|
|
rep
|
|
stosl
|
|
.Lno_fill_sbrk_memory:
|
|
movl %edx, __what_size_dpmi_thinks_we_are
|
|
|
|
.Lbrk_nochange: /* successful return */
|
|
movl __what_we_return_to_app_as_old_size, %eax
|
|
jmp .Lbrk_return
|
|
|
|
.Lbrk_error: /* error return */
|
|
movl __what_we_return_to_app_as_old_size, %eax
|
|
movl %eax, __what_size_app_thinks_it_is
|
|
movl $0, %eax
|
|
|
|
.Lbrk_return:
|
|
popl %ebx
|
|
popl %edi
|
|
popl %esi
|
|
ret
|
|
|
|
/* From here on this are parts of crt1.c converted to assembler
|
|
and without any call to libc, so that it works without anything else
|
|
additions made by Pierre Muller*/
|
|
/* from dpmidefs.h * /
|
|
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
|
|
/* from include <libc/asmdefs.h> */
|
|
/* all macros removed here */
|
|
/* #define FUNC(x) .globl x; x: */
|
|
|
|
/* #define ENTER pushl %ebp; movl %esp,%ebp */
|
|
|
|
/* #define LEAVE(x) movl %ebp,%esp; popl %ebp; ret $(x) */
|
|
/* #define ARG1 8(%ebp)
|
|
#define ARG1h 10(%ebp)
|
|
#define ARG2 12(%ebp)
|
|
#define ARG2h 14(%ebp)
|
|
#define ARG3 16(%ebp)
|
|
#define ARG4 20(%ebp)
|
|
#define ARG5 24(%ebp)
|
|
#define ARG6 28(%ebp)
|
|
#define ARG7 32(%ebp)
|
|
#define ARG8 36(%ebp) */
|
|
|
|
.comm ___dpmi_error,2
|
|
|
|
/* from dpmi0000.s */
|
|
/* .globl ___dpmi_allocate_ldt_descriptors */
|
|
/* using pascal convention => not usabel by C code */
|
|
___dpmi_allocate_ldt_descriptors:
|
|
pushl %ebp; movl %esp,%ebp
|
|
|
|
movl 8(%ebp), %ecx
|
|
movl $0x0000, %eax
|
|
int $0x31
|
|
jnc .L_noerror0000
|
|
movw %ax,___dpmi_error
|
|
movl $-1,%eax
|
|
jmp .L_leave0000
|
|
.L_noerror0000:
|
|
movzwl %ax,%eax
|
|
.L_leave0000:
|
|
movl %ebp,%esp
|
|
popl %ebp
|
|
ret $4
|
|
|
|
/* from file dpmi0008.s */
|
|
/* .globl ___dpmi_set_segment_limit */
|
|
___dpmi_set_segment_limit:
|
|
pushl %ebp; movl %esp,%ebp
|
|
|
|
movl 8(%ebp), %ebx
|
|
movzwl 12(%ebp), %edx
|
|
movzwl 14(%ebp),%ecx
|
|
|
|
movl $0x0008,%eax
|
|
int $0x31
|
|
jnc .L_noerror0008
|
|
movw %ax,___dpmi_error
|
|
movl $-1,%eax
|
|
jmp .L_leave0008
|
|
.L_noerror0008:
|
|
xorl %eax,%eax
|
|
.L_leave0008:
|
|
movl %ebp,%esp
|
|
popl %ebp
|
|
ret $8
|
|
|
|
/* .globl ___dpmi_get_version */
|
|
___dpmi_get_version:
|
|
pushl %ebp; movl %esp,%ebp
|
|
|
|
movl $0x0400,%eax
|
|
int $0x31
|
|
jnc .L_noerror0400
|
|
movw %ax,___dpmi_error
|
|
movl $-1,%eax
|
|
jmp .L_leave0400
|
|
.L_noerror0400:
|
|
movl 8(%ebp), %esi
|
|
movb %ah, (%esi)
|
|
movb %al, 1(%esi)
|
|
movw %bx, 2(%esi)
|
|
movb %cl, 4(%esi)
|
|
movb %dh, 5(%esi)
|
|
movb %dl, 6(%esi)
|
|
|
|
xorl %eax,%eax
|
|
.L_leave0400:
|
|
|
|
movl %ebp,%esp
|
|
popl %ebp
|
|
ret $4
|
|
|
|
_set_os_trueversion:
|
|
pushl %ebp
|
|
movl %esp,%ebp
|
|
movl $0x3306,%eax
|
|
xorl %ebx,%ebx
|
|
int $0x21
|
|
movzbl %bl,%eax
|
|
shll $8,%eax
|
|
shrl $8,%ebx
|
|
andl $0xff,%ebx
|
|
addl %ebx,%eax
|
|
movw %ax,__os_trueversion
|
|
popl %ebp
|
|
ret
|
|
/* .globl ___dpmi_get_segment_base_address*/
|
|
___dpmi_get_segment_base_address:
|
|
pushl %ebp; movl %esp,%ebp
|
|
|
|
movl 8(%ebp), %ebx
|
|
movl $0x0006,%eax
|
|
int $0x31
|
|
jnc .L_noerror0006
|
|
movw %ax,___dpmi_error
|
|
movl $-1,%eax
|
|
jmp .L_leave0006
|
|
.L_noerror0006:
|
|
|
|
movl 12(%ebp), %ebx
|
|
movl %edx, (%ebx)
|
|
movw %cx, 2(%ebx)
|
|
|
|
xorl %eax,%eax
|
|
.L_leave0006:
|
|
movl %ebp,%esp
|
|
popl %ebp
|
|
ret $8
|
|
|
|
.globl ___bss_count
|
|
.data
|
|
.align 2
|
|
___bss_count:
|
|
.long 1
|
|
.text
|
|
.align 2
|
|
.globl _setup_core_selector
|
|
_setup_core_selector:
|
|
pushl %ebp
|
|
movl %esp,%ebp
|
|
pushl $1
|
|
call ___dpmi_allocate_ldt_descriptors
|
|
/* addl $4,%esp */
|
|
cmpl $-1,%eax
|
|
jne .L24
|
|
movw $0,operatingsystem_go32_info_block+26
|
|
leave
|
|
ret
|
|
.align 2,0x90
|
|
.L24:
|
|
movw %ax,operatingsystem_go32_info_block+26
|
|
movw %ax,_core_selector
|
|
pushl $0x10ffff
|
|
andl $0xffff,%eax
|
|
pushl %eax
|
|
call ___dpmi_set_segment_limit
|
|
leave
|
|
ret
|
|
.align 2
|
|
.globl _setup_screens
|
|
_setup_screens:
|
|
pushl %ebp
|
|
movl %esp,%ebp
|
|
movw operatingsystem_go32_info_block+26,%dx
|
|
movl $1048563,%ecx
|
|
/APP
|
|
movw %dx, %gs
|
|
.byte 0x65
|
|
movw (%ecx),%ax
|
|
/NO_APP
|
|
cmpw $64896,%ax
|
|
jne .L26
|
|
movl $655360,operatingsystem_go32_info_block+8
|
|
movl $655360,operatingsystem_go32_info_block+4
|
|
leave
|
|
ret
|
|
.align 2,0x90
|
|
.L26:
|
|
movl $1097,%ecx
|
|
/APP
|
|
movw %dx,%gs
|
|
.byte 0x65
|
|
movb (%ecx),%al
|
|
/NO_APP
|
|
cmpb $7,%al
|
|
jne .L29
|
|
movl $720896,operatingsystem_go32_info_block+4
|
|
movl $753664,operatingsystem_go32_info_block+8
|
|
leave
|
|
ret
|
|
.align 2,0x90
|
|
.L29:
|
|
movl $753664,operatingsystem_go32_info_block+4
|
|
movl $720896,operatingsystem_go32_info_block+8
|
|
leave
|
|
ret
|
|
|
|
.align 2
|
|
.globl _setup_go32_info_block
|
|
_setup_go32_info_block:
|
|
pushl %ebp
|
|
movl %esp,%ebp
|
|
subl $8,%esp
|
|
leal -8(%ebp),%eax
|
|
pushl %eax
|
|
call ___dpmi_get_version
|
|
movl $40,operatingsystem_go32_info_block
|
|
movl __stubinfo,%edx
|
|
movzwl 36(%edx),%eax
|
|
sall $4,%eax
|
|
movl %eax,operatingsystem_go32_info_block+12
|
|
movzwl 32(%edx),%ecx
|
|
movl %ecx,operatingsystem_go32_info_block+16
|
|
movzwl 38(%edx),%ecx
|
|
movl %ecx,operatingsystem_go32_info_block+20
|
|
movb -3(%ebp),%al
|
|
movb %al,operatingsystem_go32_info_block+24
|
|
movb -2(%ebp),%al
|
|
movb %al,operatingsystem_go32_info_block+25
|
|
movl $-1,operatingsystem_go32_info_block+28
|
|
pushl $operatingsystem_go32_info_block+32
|
|
movzwl 38(%edx),%eax
|
|
pushl %eax
|
|
call ___dpmi_get_segment_base_address
|
|
movw $4,operatingsystem_go32_info_block+36
|
|
movb -8(%ebp),%dl
|
|
salw $8,%dx
|
|
movzbw -7(%ebp),%ax
|
|
orw %ax,%dx
|
|
movw %dx,operatingsystem_go32_info_block+38
|
|
call copy_to_c_go32_info_block
|
|
leave
|
|
ret
|
|
|
|
copy_to_c_go32_info_block:
|
|
leal operatingsystem_go32_info_block,%esi
|
|
leal __go32_info_block,%edi
|
|
movl $10,%ecx
|
|
rep
|
|
movsl
|
|
ret
|
|
|
|
.data
|
|
/* fpu codeword */
|
|
___fpucw:
|
|
.long 0x1332
|
|
/* __go32_info_block for C programs */
|
|
.align 2
|
|
.globl __go32_info_block
|
|
.comm __go32_info_block,40
|
|
|
|
/*
|
|
-- prt1_startup --
|
|
*/
|
|
.text
|
|
.align 2
|
|
.globl ___prt1_startup
|
|
___prt1_startup:
|
|
pushl %ebp
|
|
movl %esp,%ebp
|
|
pushl %ebx
|
|
incl ___bss_count
|
|
movl $0,___crt0_argv
|
|
call _set_os_trueversion
|
|
call _setup_core_selector
|
|
call _setup_screens
|
|
call _setup_go32_info_block
|
|
incl ___environ_changed
|
|
/* call set_processor emulation */
|
|
/* neede to avoid FPU exception if calling from anothe DPMI program */
|
|
movl $0xe01,%eax
|
|
movl $1,%ebx
|
|
int $0x31
|
|
fninit /* initialize fpu */
|
|
push %eax /* Dummy for status store check */
|
|
movl %esp,%esi
|
|
movw $0x5a5a,(%esi)
|
|
/* fwait maybe this one is responsible of exceptions */
|
|
fnstsw (%esi)
|
|
cmpb $0,(%esi)
|
|
jne .Lno_387
|
|
fldcw ___fpucw
|
|
.Lno_387:
|
|
popl %eax
|
|
pushl operatingsystem_parameter_envp
|
|
pushl ___crt0_argv
|
|
pushl ___crt0_argc
|
|
call _pascal_start
|
|
pushl %eax
|
|
/* call _exit changed to */
|
|
call exit
|
|
.align 2,0x90
|
|
/* .comm dos_argv0,4 */
|
|
.comm ___dos_argv0,4
|
|
.comm ___crt0_argc,4
|
|
.comm ___crt0_argv,4
|
|
.comm ___environ_changed,4
|
|
/* ___environ_changed: not in data because it is defined in putenv.c */
|
|
/* .long 0 */
|
|
.globl _exception_exit
|
|
_exception_exit:
|
|
.long 0
|
|
.globl _swap_in
|
|
_swap_in:
|
|
.long 0
|
|
.globl _swap_out
|
|
_swap_out:
|
|
.long 0
|
|
.global _v2prt0_exceptions_on
|
|
_v2prt0_exceptions_on:
|
|
.long 0
|
|
|
|
// Fill null page with NOPs
|
|
// and a jmp windows_error at the end
|
|
.globl v2prt0_windows
|
|
v2prt0_windows:
|
|
movl $0x90909090,%eax
|
|
xorl %edi,%edi
|
|
movl $0x400,%ecx
|
|
cld
|
|
rep
|
|
stosl
|
|
movl $0xffB,%edi
|
|
movb $0xe9,%al
|
|
stosb
|
|
movl $_fpc_windows_error-4,%eax
|
|
subl %edi,%eax
|
|
stosl
|
|
ret
|
|
|
|
// Raise SIGILL with UD2 opcode
|
|
|
|
.globl _fpc_windows_error
|
|
_fpc_windows_error:
|
|
cmpl $0,_exception_exit
|
|
je .L_error_216
|
|
.byte 0x0f,0x0b
|
|
.L_error_216:
|
|
pushl $216
|
|
call __exit
|
|
jmp exit
|
|
#enif
|
|
|
|
/* this was the prt0.s from the go32v1 version */
|
|
//
|
|
// call as start(argc, argv, envp) (C-calling convention)
|
|
//
|
|
.globl _pascal_start
|
|
_pascal_start:
|
|
/* %ebx doesn't contain ScreenPrimary */
|
|
movl operatingsystem_go32_info_block+4,%ebx
|
|
movl %ebx,_ScreenPrimary
|
|
/* core selector in %fs */
|
|
/* keep original fs for debuggers !!!!! (PM) */
|
|
movw %fs,%ax
|
|
movw %ax,___v2prt0_start_fs
|
|
|
|
movw _core_selector,%ax
|
|
movw %ax,%fs
|
|
|
|
// Top of frame
|
|
movl $0x0,%ebp
|
|
movl %esp,%ebx
|
|
movl 12(%ebx),%eax
|
|
movl %eax,operatingsystem_parameter_envp
|
|
movl %eax,__environ
|
|
movl %eax,_environ
|
|
movl 8(%ebx),%eax
|
|
movl %eax,_args
|
|
movl 4(%ebx),%eax
|
|
movl %eax,_argc
|
|
|
|
call PASCALMAIN
|
|
movl $0,%eax
|
|
/* no error if passing here */
|
|
/* movl $0x4c00,%eax
|
|
int $0x21 */
|
|
|
|
ret
|
|
|
|
.data
|
|
|
|
/* .comm operatingsystem_parameter_envp,4 */
|
|
.globl _ScreenPrimary
|
|
_ScreenPrimary:
|
|
.long 0
|
|
.globl _argc
|
|
_argc:
|
|
.long 0
|
|
.globl _args
|
|
_args:
|
|
.long 0
|
|
.globl _run_mode
|
|
_run_mode:
|
|
.word 4
|
|
.globl _core_selector
|
|
_core_selector:
|
|
.word 0
|
|
.globl ___v2prt0_start_fs
|
|
___v2prt0_start_fs:
|
|
.word 0
|
|
/* DJGPP CVS crt1.c code uses __environ symbol */
|
|
/* corresponding to _environ C variable */
|
|
/* instead of _environ symbol since commit rev 1.11 */
|
|
/* Thu Aug 19 9:11:52 2004 UTC by peuha */
|
|
/* Provide both here to avoid crt1.o loading. */
|
|
.comm __environ,4
|
|
.comm _environ,4
|
|
|
|
|
|
/* Here Pierre Muller added all what was in crt1.c */
|
|
/* in assembler */
|
|
/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
|
|
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
|
|
/* adapted to assembler for FPC by Pierre Muller */
|
|
|
|
/* Global variables */
|
|
|
|
|
|
/* This gets incremented each time the program is started.
|
|
Programs (such as Emacs) which dump their code to create
|
|
a new executable, cause this to be larger than 2. Library
|
|
functions that cache info in static variables should check
|
|
the value of `__bss_count' if they need to reinitialize
|
|
the static storage. */
|
|
.data
|
|
.globl ___bss_count
|
|
___bs_count:
|
|
.long 1
|
|
|
|
.globl __dos_ds
|
|
__dos_ds:
|
|
.long 0
|
|
|
|
.globl ___PROXY
|
|
___PROXY:
|
|
.ascii " !proxy"
|
|
.byte 0
|
|
|
|
.globl ___PROXY_LEN
|
|
___PROXY_LEN:
|
|
.long 7
|
|
|
|
.comm __os_trueversion,2
|