dos16m.asm

来自「开放源码的编译器open watcom 1.6.0版的源代码」· 汇编 代码 · 共 563 行 · 第 1/2 页

ASM
563
字号
__end_16M       label word
verylast ends

        assume  nothing
        public  _cstart_
        public  _Not_Enough_Memory_

        assume  cs:_TEXT

 _startup_ proc near
        dd      stackavail_
_cstart_:
        jmp     around

;
; copyright message
;
include msgrt16.inc
include msgcpyrt.inc

;
; miscellaneous code-segment messages
;
NullAssign      db      0dh,0ah,'*** NULL assignment detected',0dh,0ah,0

NoMemory        db      'Not enough memory',0dh,0ah,0
ConsoleName     db      'con',00h

__OurDS         dw      0

msg_notPM db    'requires DOS/16M', 0Ah, 0Dh, '$'

_Not_Enough_Memory_:
        mov     bx,1                    ; - set exit code
        mov     ax,offset NoMemory      ;
        mov     dx,cs                   ;
        call    __fatal_runtime_error_  ; - display msg and exit

around:
        mov     ax, 0FF00h              ; *RSI* see if DOS/16M really there
        mov     dx, 78h                 ; set illegal mem strategy
        int     21h                     ; maybe DOS, maybe DOS/16M
        inc     ax                      ; DOS/16M returns -1 in ax
        jz      setup                   ; okay, DOS/16M active
        mov     ah, 9                   ; not DOS/16M, display error
        mov     dx, offset _text:msg_notPM
        push    cs
        pop     ds
        int     21h                     ; with a message
        mov     ax, 4CFFh               ; and return code -1
        int     21h

setup:  sti                             ; enable interrupts
        mov     cx,DGROUP               ; get proper stack segment

        assume  es:DGROUP

        mov     es,cx                   ; point to data segment
        mov     bx,offset DGROUP:_end   ; get bottom of stack
        add     bx,0Fh                  ; ...
        and     bl,0F0h                 ; ...
        mov     es:_STACKLOW,bx         ; ...
        mov     es:_psp,ds              ; save segment address of PSP

        mov     bx,offset DGROUP:verylast ; get top of stack
        add     bx, 15                  ; round up to paragraph boundary
        and     bx, 0FFF0h              ; ...
        jne     not64k                  ; if 64K
        mov     bx,0fffeh               ; - set _curbrk to 0xfffe
not64k:                                 ; endif
        mov     es:_curbrk,bx           ; set top of memory owned by process
        mov     ss,cx                   ; set stack segment
        mov     sp,bx                   ; set sp relative to DGROUP
        mov     es:_STACKTOP,bx         ; set stack top
;
        mov     di,ds                   ; point es to PSP
        mov     es,di                   ; ...
;
;       copy command line into bottom of stack
;
        mov     di,81H                  ; DOS command buffer ds:si
        mov     cl,-1[di]               ; get length of command
        mov     ch,0
        cld                             ; set direction forward
        mov     al,' '
        repe    scasb
        lea     si,-1[di]

        mov     dx,DGROUP
        mov     es,dx                   ; es:di is destination
        mov     di,es:_STACKLOW
        mov     es:_LpCmdLine+0,di      ; stash lpCmdLine pointer
        mov     es:_LpCmdLine+2,es      ; ...
        je      noparm
        inc     cx
        rep     movsb
noparm: sub     al,al
        stosb                           ; store NULLCHAR
        mov     al,0                    ; assume no pgm name
        stosb                           ; . . .
        dec     di                      ; back up pointer 1
;
;       get DOS version number
;
        mov     ah,30h
        int     21h
        mov     es:_osmajor,al
        mov     es:_osminor,ah
        mov     cx,di                   ; remember address of pgm name
        cmp     al,3                    ; if DOS version 3 or higher
        jb      nopgmname               ; then
;
;       copy the program name into bottom of stack
;
        mov     ax,ds:2ch               ; get segment addr of environment area
        mov     dx,es:_psp              ; get segment addr of PSP

        mov     ds,ax                   ; get segment addr of environment area
        sub     si,si                   ; offset 0
        xor     bp,bp                   ; no87 not present!
L0:     mov     ax,[si]                 ; get first part of environment var
        or      ax,2020H                ; lower case
        cmp     ax,"on"                 ; if first part is 'NO'
        jne     L1                      ; - then
        mov     ax,2[si]                ; - get second part
        cmp     ax,"78"                 ; - if second part is '87'
        jne     L1                      ; - then
        inc     bp                      ; - - set bp to indicate NO87
L1:     cmp     byte ptr [si],0         ; end of string ?
        lodsb
        jne     L1                      ; until end of string
        cmp     byte ptr [si],0         ; end of all strings ?
        jne     L0                      ; if not, then skip next string
        lodsb
        inc     si                      ; - point to program name
        inc     si                      ; - . . .
L2:     cmp     byte ptr [si],0         ; - end of pgm name ?
        movsb                           ; - copy a byte
        jne     L2                      ; - until end of pgm name
nopgmname:                              ; endif
        mov     si,cx                   ; save address of pgm name
        mov     es:_LpPgmName+0,si      ; stash LpPgmName pointer
        mov     es:_LpPgmName+2,es      ; ...

        assume  ds:DGROUP
        mov     dx,DGROUP
        mov     ds,dx
        mov     es,dx
        mov     __no87,bp               ; set state of "NO87" environment var
        mov     _STACKLOW,di            ; save low address of stack

        mov     cx,offset DGROUP:_end   ; end of _BSS segment (start of STACK)
        mov     di,offset DGROUP:_edata ; start of _BSS segment
        sub     cx,di                   ; calc # of bytes in _BSS segment
        mov     al,0                    ; zero the _BSS segment
        rep     stosb                   ; . . .

        cmp     word ptr __get_ovl_stack,0 ; if program not overlayed
        jne     _is_ovl                 ; then
        mov     ax,offset __null_ovl_rtn; - set vectors to null rtn
        mov     __get_ovl_stack,ax      ; - ...
        mov     __get_ovl_stack+2,cs    ; - ...
        mov     __restore_ovl_stack,ax  ; - ...
        mov     __restore_ovl_stack+2,cs; - ...
        mov     __close_ovl_file,ax     ; - ...
        mov     __close_ovl_file+2,cs   ; - ...
_is_ovl:                                ; endif
        xor     bp,bp                   ; set up stack frame
        push    bp                      ; ... for new overlay manager
        mov     bp,sp                   ; ...
        ; DON'T MODIFY BP FROM THIS POINT ON!
        mov     ax,offset __null_FPE_rtn; initialize floating-point exception
        mov     word ptr __FPE_handler,ax       ; ... handler address
        mov     word ptr __FPE_handler+2,cs     ; ...

        mov     ax,0ffh                 ; run all initializers
        call    __FInitRtns             ; call initializer routines
        call    __CMain
_startup_ endp

;       don't touch AL in __exit, it has the return code

__exit  proc  far
        public  "C",__exit
        push    ax
        mov     dx,DGROUP
        mov     ds,dx
        cld                             ; check lower region for altered values
        lea     di,__nullarea           ; set es:di for scan
        mov     es,dx
        mov     cx,NUM_VAL
        mov     ax,INIT_VAL
        repe    scasw
        pop     ax                      ; restore return code
        je      ok
;
; low memory has been altered
;
        mov     bx,ax                   ; get exit code
        mov     ax,offset NullAssign    ; point to msg
        mov     dx,cs                   ; . . .

        public  __do_exit_with_msg__

; input: DX:AX - far pointer to message to print
;        BX    - exit code

__do_exit_with_msg__:
        mov     sp,offset DGROUP:_end+80h; set a good stack pointer
        push    bx                      ; save return code
        push    ax                      ; save address of msg
        push    dx                      ; . . .
        mov     dx,_TEXT
        mov     ds,dx
        mov     dx,offset ConsoleName
        mov     ax,03d01h               ; write-only access to screen
        int     021h
        mov     bx,ax                   ; get file handle
        pop     ds                      ; restore address of msg
        pop     dx                      ; . . .
        mov     si,dx                   ; get address of msg
        cld                             ; make sure direction forward
L3:     lodsb                           ; get char
        cmp     al,0                    ; end of string?
        jne     L3                      ; no
        mov     cx,si                   ; calc length of string
        sub     cx,dx                   ; . . .
        dec     cx                      ; . . .
        mov     ah,040h                 ; write out the string
        int     021h                    ; . . .
        pop     ax                      ; restore return code
ok:
        mov     dx,DGROUP               ; get access to DGROUP
        mov     ds,dx                   ; . . .
        cmp     byte ptr __ovlflag,0    ; if MS Overlay Manager present
        je      no_ovl                  ; then
        push    ax                      ; - save return code
        mov     al,__intno              ; - get interrupt number used
        mov     ah,25h                  ; - DOS func to set interrupt vector
        lds     dx,__ovlvec             ; - get previous contents of vector
        int     21h                     ; - restore interrupt vector
        pop     ax                      ; - restore return code
no_ovl:                                 ; endif
        push    ax                      ; save return code
        mov     ax,00h                  ; run finalizers
        mov     dx,0fh                  ; less than exit
        call    __FFiniRtns             ; call finalizer routines
        pop     ax                      ; restore return code
        mov     ah,04cH                 ; DOS call to exit with return code
        int     021h                    ; back to DOS
__exit  endp


;
;       set up addressability without segment relocations for emulator
;
public  __GETDS
__GETDS proc    near
        push    ss                      ; set DS=SS
        pop     ds                      ; ...
        ret
__GETDS endp


__null_FPE_rtn proc far
        ret                             ; return
__null_FPE_rtn endp

__null_ovl_rtn proc far
        ret                             ; return
__null_ovl_rtn endp


        public  __DOSseg__
__DOSseg__:                     ; prevent .DOSSEG from occurring

_TEXT   ends

        end     fake_start              ; mark start address in case
                                        ; program is loaded under DOS.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?