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 + -
显示快捷键?