📄 stub.asm
字号:
int 0x21printstr1: inc bx push ax ; have to preserve al set by error call mov ah, 2 int 0x21 pop ax ; restore ax (John A.)printstr: mov dl, [bx] cmp dl, '$' jne printstr1 retcrlfdollar: .db 13,10,'$';-----------------------------------------------------------------------------; DPMI utility functionszero_regs: push ax push cx push di xor ax, ax mov di, dpmi_regs mov cx, 0x19 rep stosw pop di pop cx pop ax retpm_dos: mov ax, 0x0300 ; simulate interrupt mov bx, 0x0021 ; int 21, no flags xor cx, cx ; cx = 0x0000 (copy no args) mov edi, dpmi_regs int 0x31 ret;-----------------------------------------------------------------------------; load DPMI server if not present; First check directory from which stub is loaded, then path, then default; On entry di points to image namepath_off: .dw 0 ; If stays zero, no pathload_dpmi: xor ah, ah ; Copy until this character (=0) call store_env_string ; copy stub image to "loadname" mov si, bx ; remove name so we can add DPMI name mov di, [path_off] ; Pointer to path contents (next try) jmp @f2loadloop: mov ah, ';' ; Copy until this character call store_env_string ; to "loadname" or al,al ; Check terminating character jne @f1 ; If ';', continue dec di ; else point at null for next pass.@f1: cmp si, loadname ; anything there? je do_exec ; final try (no path) let it return mov al, [si-1] call test_delim ; is final character a path delimiter je @f2 movb [si], '\\' ; no, add separator between path & name inc si@f2: call do_exec ; copy our name to string and try load jc loadloop ret;-----------------------------------------------------------------------------; add the string CWSDPMI to path endingdo_exec: call include_umb mov bx, stubinfo_dpmi_server@b1: mov al, [bx] mov [si], al inc bx inc si or al, al jne @b1; movw [si], 0x0a0d ;debug; movb [si+2], '$' ;debug push es ; Save in case of failure push di;memory saving - use dpmi_regs as a temporary parameter block push ds pop es ;zero_regs needs es set call zero_regs mov bx, dpmi_regs mov [bx+4], ds ;segment of command tail mov [bx+2], bx ;offset (point to zero) mov dx, loadname; mov ah, 9 ;debug; int 0x21 ;debug mov ax, 0x4b00 ;Do program exec int 0x21 pop di pop es jc @f1 ;carry set if exec failed mov ah, 0x4d ;get return code int 0x21 sub ax, 0x300 ;ah=3 TSR, al=code (success) neg ax ;CY, if not originally 0x300@f1: jmp restore_umb ;called func. return for us.;-----------------------------------------------------------------------------; Make upper memory allocatable. Clobbers Ax and Bx.include_umb: cmpb [dos_major], 5 ; Won't work before dos 5 jb @f1 mov ax, 0x5800 ; get allocation strategy int 0x21 mov [old_strategy],al mov ax, 0x5802 ; Get UMB status. int 0x21 mov [old_umb],al mov ax, 0x5801 mov bx, 0x0080 ; first fit, first high then low int 0x21 mov ax, 0x5803 mov bx, 0x0001 ; include UMB in memory chain int 0x21@f1: ret; Restore upper memory status. All registers and flags preserved.restore_umb: pushf cmpb [dos_major], 5 ; Won't work before dos 5 jb @f1 push ax push bx mov ax, 0x5803 ; restore UMB status. mov bl,[old_umb] xor bh, bh int 0x21 mov ax, 0x5801 ; restore allocation strategy mov bl,[old_strategy] xor bh, bh int 0x21 pop bx pop ax@f1: popf ret;-----------------------------------------------------------------------------; Stored Dataerr_string: .db "Load error: $"msg_no_progfile: .db ": can't open$"msg_not_exe: .db ": not EXE$"msg_not_coff: .db ": not COFF (Check for viruses)$"msg_no_dpmi: .db "no DPMI - Get csdpmi*b.zip$"msg_no_dos_memory: .db "no DOS memory$"msg_bad_dos: .db "need DOS 3$"msg_error_in_modesw: .db "can't switch mode$"msg_no_selectors: .db "no DPMI selectors$"msg_no_dpmi_memory: .db "no DPMI memory$";-----------------------------------------------------------------------------; Unstored Data, available during and after mode switchlast_generated_byte: .align 512 ; Align ourselves to a sector ; boundary for startup speed. .bss ; data after this isn't in file.modesw: ; address of DPMI mode switch .dd 0modesw_mem: ; amount of memory DPMI needs .dw 0program_file: ; file ID of program data .dw 0text_foffset: ; offset in file .dd 0data_foffset: ; offset in file .dd 0start_eip: ; EIP value to start at .dd 0client_cs: ; must follow start_eip .dw 0client_ds: .dw 0client_memory: .dd 0dos_block_seg: .dw 0dos_block_sel: .dw 0dos_block_size: .dw 0read_soffset: .dd 0read_size: .dd 0dpmi_regs: .db 0x32 .dup 0dr_edi = 0x00dr_di = 0x00dr_esi = 0x04dr_si = 0x04dr_ebp = 0x08dr_bp = 0x08dr_ebx = 0x10dr_bx = 0x10dr_bl = 0x10dr_bh = 0x11dr_edx = 0x14dr_dx = 0x14dr_dl = 0x14dr_dh = 0x15dr_ecx = 0x18dr_cx = 0x18dr_cl = 0x18dr_ch = 0x19dr_eax = 0x1cdr_ax = 0x1cdr_al = 0x1cdr_ah = 0x1ddr_efl = 0x20dr_es = 0x22dr_ds = 0x24dr_fs = 0x26dr_gs = 0x28dr_ip = 0x2adr_cs = 0x2cdr_sp = 0x2edr_ss = 0x30;----------------------------------------------------------------------------- .align 16 ; so that stack ends on para boundary .dw 128 .dup 0 .stack;-----------------------------------------------------------------------------; At one time real mode only data. Header stuff now used during image load.psp_segment: .dw 0loadname_nul: ; offset of NUL so it can become '$' .dw 0loadname: ; name of program file to load, if it .db 81 .dup 0 ; gets really long ok to overwrite nextexe_header: ; loaded from front of loadfileexe_magic: .dw 0exe_bytes_last_page: .dw 0exe_sectors: .dw 0exe_header_length = . - exe_headercoff_offset: .dd 0 ; from start of filecoff_header: ; loaded from after stub .db 20 .dup 0aout_header: .db 28 .dup 0text_section: .db 40 .dup 0data_section: .db 40 .dup 0bss_section: .db 40 .dup 0coff_header_length = . - coff_headerold_strategy: .db 0old_umb: .db 0dos_major: .db 0 .align 16 ; Align ourselves to a paragraphend_of_memory: ; resize is done early so must keep all;-----------------------------------------------------------------------------; structure definitions;coff_magic = 0 ; from coff headeraout_entry = 16 ; from aout headers_paddr = 8 ; from section headerss_vaddr = 12s_size = 16s_scnptr = 20
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -