home *** CD-ROM | disk | FTP | other *** search
- ; Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details
- ; -*- asm -*-
- ;
- ;-----------------------------------------------------------------------------
- ; PMODE/DJ - A stub with an inbuilt DPMI dos extender. (like PMODE/W)
- ;
- ; PMODE/DJ includes PMODE V3.07, which is (c) by Thomas Phytel
- ; PMODE/DJ was written by m.grimrath@tu-bs.de. Changes were made both to
- ; stub.asm and pmode.asm.
- ; stub.asm - changed to compile with tasm and switches into PM via PMODE
- ; pmode.asm - added some features, like exceptionhandling and PIC
- ; reprogramming, etc. See pmodedj.doc for details
- ;-----------------------------------------------------------------------------
- ;
- ; KLUDGE-WARNING!
- ;
- ; So you say you want to change this file, right? Are you really sure
- ; that's a good idea? Let me tell you a bit about the pitfalls here:
- ;
- ; * Some code runs in protected mode, some in real-mode, some in both.
- ; * Some code must run on a 8088 without crashing it.
- ; * Registers and flags may be expected to survive for a long time.
- ; * The code is optimized for size, not for speed or readability.
- ; * Some comments are parsed by other programs.
- ;
- ; You still want to change it? Oh well, go ahead, but don't come
- ; crying back saying you weren't warned.
- ;
- ;-----------------------------------------------------------------------------
- ; djgpp stub loader
- ;
- ; (C) Copyright 1993-1995 DJ Delorie
- ;
- ; Redistribution and use in source and binary forms are permitted
- ; provided that: (1) source distributions retain this entire copyright
- ; notice and comment, (2) distributions including binaries display
- ; the following acknowledgement: ``This product includes software
- ; developed by DJ Delorie and contributors to the djgpp project''
- ; in the documentation or other materials provided with the distribution
- ; and in all advertising materials mentioning features or use of this
- ; software, and (3) binary distributions include information sufficient
- ; for the binary user to obtain the sources for the binary and utilities
- ; required to built and use it. Neither the name of DJ Delorie nor the
- ; names of djgpp's contributors may be used to endorse or promote
- ; products derived from this software without specific prior written
- ; permission.
- ;
- ; THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- ; IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- ; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- ;
- ; Revision history:
- ;
- ; 93/12/05 DJ Delorie Initial version v2.00, requires DPMI 0.9
- ; 94/10/13 CW Sandmann v2.01, accumlated changes: 60K load bug, limits, cwsdpmi, optimization
- ; 94/10/29 CW Sandmann v2.03, M Welinder changes; cwsdpmi load anywhere, size decrease
- ;
- ideal
- p386
- assume cs:_TEXT, ds:DGROUP, es:nothing, ss:nothing, fs:_TEXT
- group DGROUP _DATA, _BSS
-
- SEGMENT _TEXT PUBLIC USE16 'CODE'
-
- ;*****************************************************************************
- ; structure definitions
- ;
-
- coff_magic = 0 ; from coff header
-
- aout_entry = 16 ; from aout header
-
- s_paddr = 8 ; from section headers
- s_vaddr = 12
- s_size = 16
- s_scnptr = 20
-
- stack_sz = 180h ; must be a multiple of 16!
-
- SW_FLAGS = 0002h ; switch flags for PMODE
- EXCEPTION_HANDLER = 0
- EXTRN pm_info:near, pm_init:near
-
- ;-----------------------------------------------------------------------------
- ; Interface to 32-bit executable:
- ;
- ; 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.
- ;-----------------------------------------------------------------------------
- ; This is the stubinfo structure. The presence of this structure
- ; indicates that the executable is a djgpp v2.00 executable.
- ; Fields will never be deleted from this structure, only obsoleted.
- ;
- label stubinfo byte
- stubinfo_magic \ ; char [16]
- db "go32stub, v 2.00" ; version may change, [0..7] won't
- stubinfo_size \ ; unsigned long
- dw stubinfo_end,0 ; bytes in structure
- stubinfo_minstack \ ; unsigned long
- dd 40000h ; minimum amount of DPMI stack space (256K)
- stubinfo_memory_handle \ ; unsigned long
- dd 0 ; DPMI memory handle
- stubinfo_initial_size \ ; unsigned long
- dd 0 ; size of initial segment
- stubinfo_minkeep \ ; unsigned short
- dw 16384 ; amount of automatic real-mode buffer
- stubinfo_ds_selector \ ; unsigned short
- dw 0 ; our DS selector (used for transfer buffer)
- stubinfo_ds_segment \ ; unsigned short
- dw 0 ; our DS segment (used for simulated calls)
- stubinfo_psp_selector \ ; unsigned short
- dw 0 ; PSP selector
- stubinfo_cs_selector \ ; unsigned short
- dw 0 ; to be freed
- stubinfo_env_size \ ; unsigned short
- dw 0 ; number of bytes of environment
- stubinfo_basename \ ; char [8]
- db 8 dup (0) ; base name of executable to load (asciiz if < 8)
- ;db "A",0,0,0,0,0,0,0
- stubinfo_argv0 \ ; char [16]
- db 16 dup (0) ; used ONLY by the application (asciiz if < 16)
- stubinfo_dpmi_server \ ; char [16]
- db 16 dup (0) ; used by stub to load DPMI server if no DPMI
- ; already present. Not used by PMODEDJ
- align 4
- label stubinfo_end byte
-
- ;*****************************************************************************
- ; CODE
-
- ; THIS IS NOW IN PADSEC!
- ; db "The PMODEDJ.EXE stub loader is Copyright (C) 1993-1995 DJ Delorie. ",13,10
- ; db "Permission granted to use for any purpose provided this copyright ",13,10
- ; db "remains present and unmodified. ",13,10
- ; db "This only applies to the stub, and not neccessarily the whole program.",13,10
-
- ;-----------------------------------------------------------------------------
- ; First, set up our memory and stack environment
- start: ; execution starts here
- push _DATA
- pop ds
- cld
-
- mov bp,_STACK + (stack_sz/16) ; end of needed memory
- sub bp,_TEXT ; bp = # of paragraphs without psp
- mov [dos_block_seg],es ; save psp
-
- ;-----------------------------------------------------------------------------
- ; Check that we have DOS 3.00 or later. (We need this because earlier
- ; versions don't supply argv[0] to us and will scrog registers on dpmi exec).
- mov ah, 030h
- int 021h
- mov [dos_major],al
- cmp al, 3
- jae short dos3ok
- mov dx, offset msg_bad_dos
- jmp error
- dos3ok:
-
- ;-----------------------------------------------------------------------------
- ; Get DPMI information before doing anything 386-specific
- mov ax,SW_FLAGS
- call pm_info ; get protected mode info
- jnc short @@ok
- jmp error_in_modesw
- @@ok: mov [modesw_mem], bx
- push cs
- pop fs
- cmp ch,3
- jz short @@dpmi
-
- ; PMODE/DJ is active - allocate a separate transferbuffer
- mov bx, bp
- add bx, 10h ; extra for psp
- mov es, [dos_block_seg]
- mov ah, 04ah
- int 021h ; resize our memory block
- jc error_no_dos_memory
-
- call include_umb
- mov ah,48h
- mov bx,[stubinfo_minkeep]
- shr bx,4
- int 21h ; Allocate transbuffer
- jnc short @@w1
- call restore_umb
- jmp error_no_dos_memory
- @@w1: mov [fs:stubinfo_ds_segment],ax
- call restore_umb
- jmp short @@cont
-
- ; A DPMI host is active - this loader can be overwritten
- @@dpmi: shl bp, 4
- cmp bp, [stubinfo_minkeep]
- ja short @@w2
- mov bp, [stubinfo_minkeep]
- @@w2: mov [fs:stubinfo_minkeep], bp
- mov bx, bp
- inc bh ; Add extra for psp
- shr bx, 4
- mov es, [dos_block_seg]
- mov ah, 04ah
- int 021h ; resize our memory block
- jc error_no_dos_memory
- mov [fs:stubinfo_ds_segment], cs
-
- @@cont:
- ;-----------------------------------------------------------------------------
- ; Scan environment for the stub's full name after environment
- mov es, [dos_block_seg]
- mov es, [es:02ch] ; get environment segment
- xor di, di ; begin search for NUL/NUL (di = 0)
- mov cx, 0ff04h ; effectively `infinite' loop
- xor al, al
- scan_environment:
- repne scasb ; search for NUL
- scasb
- jne short scan_environment ; no, still environment
- scasw ; adjust pointer to point to prog name
-
- ;-----------------------------------------------------------------------------
- ; copy the filename to loadname
- sub al,al
- push di
- mov cx,-1
- repne scasb
- not cx
- mov [fs:stubinfo_env_size], di
- pop si
- mov di,offset loadname
-
- push ds
- push es
- push ds
- pop es
- pop ds
- rep movsb
- pop ds
-
- mov bx,di
- @@lp2: dec bx
- cmp [byte ptr bx],'\' ; always succeeds, because filename
- jne short @@lp2 ; is qualified
- inc bx
-
- cmp [byte ptr stubinfo_basename+0], 0
- je short no_symlink
-
- ;-----------------------------------------------------------------------------
- ; Replace the stub's file name with the link's name after the directory
-
- mov cx, 8 ; max length of basename
- mov di, offset stubinfo_basename ; pointer to new basename
- @@b11:
- mov al, [cs:di] ; get next character
- inc di
- or al, al ; end of basename?
- je short @@f12
- mov [bx], al ; store character
- inc bx
- loop @@b11 ; eight characters?
- @@f12:
- mov [dword ptr bx+0], 04558452eh ; append ".EXE"
- add bx, 4
- mov [byte ptr bx], 0
-
- no_symlink:
-
- ;-----------------------------------------------------------------------------
- ; Load the COFF information from the file
-
- mov ax, 03d00h ; open file for reading
- mov dx, offset loadname
- int 021h
- jc error_no_progfile ; do rest of error message
-
- mov [program_file], ax ; store for future reference
-
- mov bx, ax
- mov cx, exe_header_length
- mov dx, offset exe_header
- mov ah, 03fh ; read EXE header
- int 021h
-
- xor dx, dx ; dx = 0
- xor cx, cx ; offset of COFF header
-
- mov ax, [exe_magic]
- cmp ax, 0014ch ; COFF?
- je short file_is_just_coff
- cmp ax, 05a4dh ; EXE magic value
- jne error_not_exe
-
- mov dx, [exe_sectors]
- shl dx, 9 ; 512 bytes per sector
- mov bx, [exe_bytes_last_page]
- or bx, bx ; is bx = 0 ?
- je short @@f13
- sub dh, 2 ; dx -= 512
- add dx, bx
- @@f13:
-
- file_is_just_coff: ; cx:dx is offset
- mov [word ptr coff_offset+0], dx
- mov [word ptr coff_offset+2], cx
- mov ax, 04200h ; seek from beginning
- mov bx, [program_file]
- int 021h
-
- mov cx, coff_header_length
- mov dx, offset coff_header
- mov ah, 03fh ; read file (bx = handle)
- int 021h
-
- cmp ax, coff_header_length
- jne short @@f21
- cmp [word ptr coff_header + coff_magic], 0014ch
- @@f21:
- jne error_not_coff
-
- mov eax, [dword ptr aout_header + aout_entry]
- mov [start_eip], eax
-
- mov ecx, [coff_offset]
-
- mov eax, [dword ptr text_section + s_scnptr]
- add eax, ecx
- mov [text_foffset], eax
-
- mov eax, [dword ptr data_section+ s_scnptr]
- add eax, ecx
- mov [data_foffset], eax
-
- mov ebx, [dword ptr bss_section + s_vaddr]
- mov eax, [dword ptr bss_section + s_size]
- add ebx, eax
- mov eax, 00010001h
- cmp ebx, eax
- jae short @@f1
- mov ebx, eax ; ensure 32-bit segment
- @@f1:
- add ebx, 0000ffffh ; ensure 64K rounded
- xor bx, bx ; clear rounded bits
- mov [fs:stubinfo_initial_size], ebx
-
- ;-----------------------------------------------------------------------------
- ; Set up for the DPMI environment
- call include_umb
- mov bx, [modesw_mem]
- or bx, bx ; or clears carry
- jz short @@noa
- mov ah, 048h ; allocate memory for the DPMI host
- int 021h
- jnc short @@noa
- call restore_umb
- jmp error_no_dos_memory
- @@noa: push ax
- call restore_umb
- pop es
- mov ax,SW_FLAGS ; switch flags
- call pm_init ; attempt to switch
- jc error_in_modesw
-
- ;-----------------------------------------------------------------------------
- ; We're in protected mode at this point.
- IF EXCEPTION_HANDLER NE 0
- push es ds
- mov bx,cs
- mov ax,000Ah
- int 31h ; create alias descriptor
- jc perror_no_selectors
- mov es,ax
- mov [es:offset exception_vector],ds
-
- mov bx,0
- sub edx,edx
- mov dx,offset exception_code
- mov cx,cs
- @@ll: mov ax,203h
- int 31h
- add dx,EXCEPTION_SIZE
- inc bx
- cmp bx,32
- jne @@ll
- pop ds es
- ENDIF
- mov bx,cs
- mov ax,000Ah
- int 31h ; create alias descriptor
- jc perror_no_selectors
- mov fs,ax
-
- mov [fs:stubinfo_psp_selector],es
- mov [fs:stubinfo_ds_selector],fs
- mov [fs:stubinfo_cs_selector],ds
- push ds
- pop es
-
- xor ax, ax ; AX = 0x0000
- mov cx, 1
- int 031h ; allocate LDT descriptor
- jc short @@f2
- mov [client_cs], ax
-
- xor ax, ax ; AX = 0x0000
- ; mov cx, 1 ; already set above
- int 031h ; allocate LDT descriptor
- @@f2:
- jc perror_no_selectors
- mov [client_ds], ax
-
- ; Try getting a DPMI 1.0 memory block first, then try DPMI 0.9
- ; Note: This causes the Borland Windows VxD to puke, commented for now with ;*
- ;* mov ax, 0x0504
- ;* xor ebx, ebx ; don't specify linear address
- mov ecx, [stubinfo_initial_size + 0]
- ;* mov edx, 1 ; allocate committed pages
- ;* int 0x31 ; allocate memory block
- ;* jc try_old_dpmi_alloc
- ;* mov client_memory[0], ebx
- ;* mov fs:stubinfo_memory_handle[0], esi
- ;* jmp got_dpmi_memory
- try_old_dpmi_alloc:
- mov ax, 00501h
- mov bx, [word ptr stubinfo_initial_size + 2]
- ; mov cx, stubinfo_initial_size[0] ;Set above
- int 031h ; allocate memory block
- jc perror_no_dpmi_memory
- mov [word ptr client_memory + 2], bx
- mov [word ptr client_memory + 0], cx
- mov [word ptr fs:stubinfo_memory_handle + 2], si
- mov [word ptr fs:stubinfo_memory_handle + 0], di
- got_dpmi_memory:
-
- mov ax, 00007h
- mov bx, [client_cs] ; initialize client CS
- mov cx, [word ptr client_memory + 2]
- mov dx, [word ptr client_memory + 0]
- int 031h ; set segment base address
-
- mov ax, 00009h
- ; mov bx, [client_cs] ; already set above
- mov cx, cs ; get CPL
- and cx, 00003h
- shl cx, 5
- push cx ; save shifted CPL for below
- or cx, 0c09bh ; 32-bit, big, code, non-conforming, readable
- int 031h ; set descriptor access rights
-
- mov ax, 00008h
- ; mov bx, [client_cs] ; already set above
- mov cx, [word ptr stubinfo_initial_size + 2]
- dec cx
- mov dx, 0ffffh
- int 031h ; set segment limit
-
- mov ax, 00007h
- mov bx, [client_ds] ; initialize client DS
- mov cx, [word ptr client_memory + 2]
- mov dx, [word ptr client_memory + 0]
- int 031h ; set segment base address
-
- mov ax, 00009h
- ; mov bx, [client_ds] ; already set above
- pop cx ; shifted CPL from above
- or cx, 0c093h ; 32-bit, big, data, r/w, expand-up
- int 031h ; set descriptor access rights
-
- mov ax, 00008h
- ; mov bx, [client_ds] ; already set above
- mov cx, [word ptr stubinfo_initial_size + 2]
- dec cx
- mov dx, 0ffffh
- int 031h ; set segment limit
-
- ;-----------------------------------------------------------------------------
- ; Load the program data
-
- mov ax, 00100h
- mov bx, 00f00h ; 60K DOS block size
- int 031h ; allocate DOS memory
- jnc short @@f1
- cmp ax, 00008h
- jne perror_no_dos_memory
- mov ax, 00100h ; try again with new value in bx
- int 031h ; allocate DOS memory
- jc perror_no_dos_memory
- @@f1:
- mov [dos_block_seg], ax
- mov [dos_block_sel], dx
- shl bx, 4 ; paragraphs to bytes
- mov [dos_block_size], bx
-
- mov esi, [text_foffset] ; load text section
- mov edi, [dword ptr text_section + s_vaddr]
- mov ecx, [dword ptr text_section + s_size]
- call read_section
-
- mov esi, [data_foffset] ; load data section
- mov edi, [dword ptr data_section + s_vaddr]
- mov ecx, [dword ptr data_section + s_size]
- call read_section
-
- mov es, [client_ds] ; clear the BSS section
- mov edi, [dword ptr bss_section + s_vaddr]
- mov ecx, [dword ptr bss_section + s_size]
- xor eax,eax
- shr ecx,2
- rep stos [dword ptr es:edi]
-
- mov ah,03eh
- mov bx, [program_file]
- int 021h ; close the file
-
- mov ax, 00101h
- mov dx, [dos_block_sel]
- int 031h ; free the DOS memory
-
- push [dword ptr client_cs]
- push [dword ptr start_eip] ; push entry address
- push [client_ds]
-
- mov bx,fs
- movzx edx,[stubinfo_ds_segment]
- shl edx,4
- shld ecx,edx,16
- mov ax,007h
- int 31h ; set fs to transferbuffer
-
- mov bx,ds
- mov ax,007h
- int 31h ; set ds to buffer also
-
- push fs
- pop es
- sub si,si ; offset of stubinfo in codesegment
- sub di,di ; transferbuffer
- mov cx,(stubinfo_end - stubinfo)
- rep movs [byte ptr es:di],[byte ptr cs:si] ; copy stubinfo structure
- push ds di ; little wrapper
- mov [dword ptr es:di], 0CD0001B8h
- mov [dword ptr es:di+4], 0CB661F31h
-
- mov cx,cs ; set ds to 16 bit code
- and cx,3
- shl cx,5
- or cl,9Ah
- mov ax,009h
- int 31h
-
- mov bx,cs
- retf ; jump to wrapper
-
- ;-----------------------------------------------------------------------------
- ; Read a section from the program file
-
- read_section:
- mov eax, esi ; sector alignment by default
- and eax, 01ffh
- add ecx, eax
- sub si, ax ; sector align disk offset (can't carry)
- sub edi, eax ; memory maybe not aligned!
-
- mov [read_size], ecx ; store for later reference
- mov [read_soffset], edi
-
- call zero_regs
- mov [word ptr dpmi_regs + dr_dx], si ; store file offset
- shr esi, 16
- mov [word ptr dpmi_regs + dr_cx], si
- mov bx, [program_file]
- mov [word ptr dpmi_regs + dr_bx], bx
- mov [word ptr dpmi_regs + dr_ax], 04200h
- call pm_dos ; seek to start of data
-
- ; Note, handle set above
- mov ax, [dos_block_seg]
- mov [word ptr dpmi_regs + dr_ds], ax
- mov [word ptr dpmi_regs + dr_dx], 0 ; store file offset
- read_loop:
- mov [byte ptr dpmi_regs + dr_ah], 03fh
- mov ax, [word ptr read_size + 2] ; see how many bytes to read
- or ax, ax
- jnz short read_too_big
- mov ax, [word ptr read_size + 0]
- cmp ax, [dos_block_size]
- jna short read_size_in_ax ; jna shorter than jmp
- read_too_big:
- mov ax, [dos_block_size]
- read_size_in_ax:
- mov [word ptr dpmi_regs + dr_cx], ax
- call pm_dos ; read the next chunk of file data
-
- xor ecx, ecx
- mov cx, [word ptr dpmi_regs + dr_ax] ; get byte count
- mov edi, [read_soffset] ; adjust pointers
- add [read_soffset], ecx
- sub [read_size], ecx
-
- xor esi, esi ; esi=0 offset for copy data
- shr cx, 2 ; ecx < 64K
- push ds
- push es
- mov es, [client_ds]
- mov ds, [dos_block_sel]
- rep movs [dword ptr es:edi],[dword ptr ds:esi]
- pop es
- pop ds
-
- add ecx, [read_size] ; ecx zero from the rep movsd
- jnz read_loop
-
- ret
-
- ;-----------------------------------------------------------------------------
- ; Most errors come here, early ones jump direct (8088 instructions)
-
- error_no_progfile:
- mov dx, offset msg_no_progfile
- jmp short error_fn
-
- error_not_exe:
- mov dx, offset msg_not_exe
- jmp short error_fn
-
- error_not_coff:
- mov dx, offset msg_not_coff
- ; jmp error_fn
-
- error_fn:
- push dx
- mov bx, offset loadname
- jmp short error_in
-
- error_no_dos_memory:
- mov dx, offset msg_no_dos_memory
- jmp short error
-
- error_in_modesw:
- mov dx, offset msg_error_in_modesw
- jmp short error
-
- perror_no_selectors:
- mov dx, offset msg_no_selectors
- jmp short error
-
- perror_no_dpmi_memory:
- mov dx, offset msg_no_dpmi_memory
- jmp short error
-
- perror_no_dos_memory:
- mov dx, offset msg_no_dos_memory
- ; jmp error
-
- error:
- push dx
- mov bx, offset err_string
- error_in:
- call printstr
- pop bx
- call printstr
- exit:
- mov bx, offset crlfdollar
- call printstr
- mov ax, 04cffh ; error exit
- int 021h
-
- printstr1:
- inc bx
- mov ah, 2
- int 021h
- printstr:
- mov dl, [bx]
- cmp dl, 0
- jne printstr1
- ret
-
- ;-----------------------------------------------------------------------------
- ; DPMI utility functions
-
- zero_regs:
- push ax
- push cx
- push di
- xor ax, ax
- mov di, offset dpmi_regs
- mov cx, 019h
- rep
- stosw
- pop di
- pop cx
- pop ax
- ret
-
- pm_dos:
- mov ax, 00300h ; simulate interrupt
- mov bx, 00021h ; int 21, no flags
- xor cx, cx ; cx = 0x0000 (copy no args)
- sub edi,edi
- mov di, offset dpmi_regs
- int 031h
- ret
-
- include_umb:
- cmp [dos_major], 5 ; Won't work before dos 5
- jb short @f1
- mov ax, 05800h ; get allocation strategy
- int 021h
- mov [old_strategy],al
- mov ax, 05802h ; Get UMB status.
- int 021h
- mov [old_umb],al
- mov ax, 05801h
- mov bx, 00080h ; first fit, first high then low
- int 021h
- mov ax, 05803h
- mov bx, 00001h ; include UMB in memory chain
- int 021h
- @f1: ret
-
- restore_umb:
- cmp [dos_major], 5 ; Won't work before dos 5
- jb short @f2
- mov ax, 05803h ; restore UMB status.
- mov bl,[old_umb]
- xor bh, bh
- int 021h
- mov ax, 05801h ; restore allocation strategy
- mov bl,[old_strategy]
- xor bh, bh
- int 021h
- @f2: ret
-
- IF EXCEPTION_HANDLER NE 0
-
- STRUC tRegs
- edi dd ?
- esi dd ?
- ebp dd ?
- res dd ?
- ebx dd ?
- edx dd ?
- ecx dd ?
- eax dd ?
- flags dw ?
- es dw ?
- ds dw ?
- fs dw ?
- gs dw ?
- ip dw ?
- cs dw ?
- sp dw ?
- ss dw ?
- esp dd ? ; My own extensions
- eip dd ?
- eflags dd ?
- cr2 dd ?
- ENDS
-
- exception_code:
- count = 0
- REPT 32
- DB 68h
- DW count ; push exception number
- DB 0E9h
- DW exception_handler - 2 - $ ; jmp exception_handler
- count = count +1
- ENDM
- EXCEPTION_SIZE = ($ - exception_code) / 32
-
- MACRO CONVW dst,num
- mov cl,4
- mov dx,num
- mov bx,offset dst
- call conv_hex
- ENDM
-
- MACRO CONVD dst,num
- mov cl,8
- mov edx,num
- mov bx,offset dst
- call conv_hex
- ENDM
-
- public exception_vector, exception_handler
- exception_handler:
- push ds ebp
-
- mov bp,0
- exception_vector = $-2
- mov ds,bp
- mov [exp_rg.eax],eax
- mov [exp_rg.ebx],ebx
- mov [exp_rg.ecx],ecx
- mov [exp_rg.edx],edx
- mov [exp_rg.esi],esi
- mov [exp_rg.edi],edi
- mov [exp_rg.es],es
- mov [exp_rg.fs],fs
- mov [exp_rg.gs],gs
-
- mov ebp,esp
- mov eax,[ebp]
- mov [exp_rg.ebp],eax
- mov ax,[ebp+4]
- mov [exp_rg.ds],ax
-
- mov eax,[ebp+8+3*4] ; Get cs:eip
- mov [exp_rg.eip],eax
- mov ax,[ebp+8+4*4]
- mov [exp_rg.cs],ax
-
- mov eax,[ebp+8+5*4]
- mov [exp_rg.eflags],eax ; Get eflags
- mov eax,[ebp+8+6*4]
- mov [exp_rg.esp],eax
- mov ax,[ebp+8+7*4]
- mov [exp_rg.ss],ax ; Get ss:esp
-
- mov eax,cr2
- mov [exp_rg.cr2],eax
-
- push ds
- pop es
- CONVW exctype,[ebp+6]
- CONVW excerr,[ebp+8+2*4]
- CONVD exceax,[exp_rg.eax]
- CONVD excebx,[exp_rg.ebx]
- CONVD excecx,[exp_rg.ecx]
- CONVD excedx,[exp_rg.edx]
- CONVD excesi,[exp_rg.esi]
- CONVD excedi,[exp_rg.edi]
- CONVD excebp,[exp_rg.ebp]
- CONVW excds,[exp_rg.ds]
- CONVW exces,[exp_rg.es]
- CONVW excfs,[exp_rg.fs]
- CONVW excgs,[exp_rg.gs]
- CONVW exccs,[exp_rg.cs]
- CONVD exceip,[exp_rg.eip]
- CONVD excflgs,[exp_rg.eflags]
- CONVW excss,[exp_rg.ss]
- CONVD excesp,[exp_rg.esp]
- CONVD exccr2,[exp_rg.cr2]
-
- mov bx,offset excerror
- call printstr
-
- mov ax,04CFFh
- int 21h ; terminate
-
- ; in: es:bx = stringbuffer, cl = # of digits, edx = number
- ; out: ax,bx,cl,edx = trashed
- conv_hex:
- push si
- shl cl,2
- ror edx,cl
- shr cl,2
- @@ll: rol edx,4 ; get digit
- mov si,15
- and si,dx ; mask out
- mov al,[hexbuffer + si]
- mov [es:bx],al ; store converted digit
- inc bx
- dec cl
- jne @@ll
- pop si
- ret
-
- ENDIF
-
- ENDS
-
- ;*****************************************************************************
- ; Data
- SEGMENT _DATA PUBLIC USE16 'DATA'
-
- IF EXCEPTION_HANDLER NE 0
- align 4 ; Align ourselves to a paragraph
- exp_rg tRegs ?
- hexbuffer db '0123456789ABCDEF'
- label excerror byte
- db 'exception #'
- exctype db 'xxxx occured with error code '
- excerr db 'xxxx',13,10
- db 'eax='
- exceax db 'xxxxxxxx ebx='
- excebx db 'xxxxxxxx ecx='
- excecx db 'xxxxxxxx edx='
- excedx db 'xxxxxxxx',13,10,'esi='
- excesi db 'xxxxxxxx edi='
- excedi db 'xxxxxxxx ebp='
- excebp db 'xxxxxxxx',13,10
- db 'ds='
- excds db 'xxxx es='
- exces db 'xxxx fs='
- excfs db 'xxxx gs='
- excgs db 'xxxx',13,10
- db 'cs:eip='
- exccs db 'xxxx:'
- exceip db 'xxxxxxxx eflags='
- excflgs db 'xxxxxxxx ss:esp='
- excss db 'xxxx:'
- excesp db 'xxxxxxxx cr2='
- exccr2 db 'xxxxxxxx',13,10
- db 0
- align 4
- ENDIF
-
- ;-----------------------------------------------------------------------------
- ; Stored Data
- err_string db "Load error: ",0
- msg_no_progfile db ": cannot open",0
- msg_not_exe db ": not EXE",0
- msg_not_coff db ": not COFF",0
- msg_no_dpmi db "no DPMI",0
- msg_no_dos_memory db "no DOS memory",0
- msg_bad_dos db "need DOS 3",0
- msg_error_in_modesw db "can't switch mode",0
- msg_no_selectors db "no DPMI selectors",0
- msg_no_dpmi_memory db "no DPMI memory",0
- crlfdollar db 13,10,0
-
- label last_generated_byte byte ; data after this isn't in file.
- ENDS
-
- ;-----------------------------------------------------------------------------
- ; Unstored Data, available during and after mode switch
- SEGMENT _BSS PUBLIC USE16 'BSS'
- modesw_mem dw ? ; amount of memory DPMI needs
- program_file dw ? ; file ID of program data
- text_foffset dd ? ; offset in file
- data_foffset dd ? ; offset in file
- start_eip dd ? ; EIP value to start at
- client_cs dw ? ; must follow start_eip
- client_ds dw ?
-
- client_memory dd ?
-
- dos_block_seg dw ?
- dos_block_sel dw ?
- dos_block_size dw ?
-
- read_soffset dd ?
- read_size dd ?
-
- dos_major db ?
- old_umb db ?
- old_strategy db ?
-
- ALIGN 2
- dpmi_regs db 32h dup (?)
- dr_edi = 000h
- dr_di = 000h
- dr_esi = 004h
- dr_si = 004h
- dr_ebp = 008h
- dr_bp = 008h
- dr_ebx = 010h
- dr_bx = 010h
- dr_bl = 010h
- dr_bh = 011h
- dr_edx = 014h
- dr_dx = 014h
- dr_dl = 014h
- dr_dh = 015h
- dr_ecx = 018h
- dr_cx = 018h
- dr_cl = 018h
- dr_ch = 019h
- dr_eax = 01ch
- dr_ax = 01ch
- dr_al = 01ch
- dr_ah = 01dh
- dr_efl = 020h
- dr_es = 022h
- dr_ds = 024h
- dr_fs = 026h
- dr_gs = 028h
- dr_ip = 02ah
- dr_cs = 02ch
- dr_sp = 02eh
- dr_ss = 030h
-
- ;-----------------------------------------------------------------------------
- ; At one time real mode only data. Header stuff now used during image load.
-
- loadname db 81 dup (?) ; name of program file to load, if it
- ; gets really long ok to overwrite next
-
- label exe_header byte ; loaded from front of loadfile
- exe_magic dw ?
- exe_bytes_last_page dw ?
- exe_sectors dw ?
- exe_header_length = $ - exe_header
-
- coff_offset dd ? ; from start of file
-
- coff_header db 20 dup (?) ; loaded from after stub
-
- aout_header db 28 dup (?)
- text_section db 40 dup (?)
- data_section db 40 dup (?)
- bss_section db 40 dup (?)
- coff_header_length = $ - coff_header
-
- ENDS
-
- SEGMENT _STACK STACK 'STACK'
- db stack_sz dup (?)
- ENDS
-
- END start
-
-