📄 stub.asm
字号:
jae @f1 mov ebx, eax ; ensure 32-bit segment@f1: add ebx, 0x0000ffff ; ensure 64K rounded xor bx, bx ; clear rounded bits mov [stubinfo_initial_size], ebx;-----------------------------------------------------------------------------; Set up for the DPMI environment call include_umb mov bx, [modesw_mem] or bx, bx jz no_dos_alloc mov ah, 0x48 ; allocate memory for the DPMI host int 0x21 jcl error_no_dos_memory_umb mov es, axno_dos_alloc: call restore_umb mov ax, 1 ; indicates a 32-bit client callf [modesw] ; enter protected mode jcl error_in_modesw;-----------------------------------------------------------------------------; We're in protected mode at this point. mov [stubinfo_psp_selector], es mov [stubinfo_cs_selector], cs mov ax, ds mov [stubinfo_ds_selector], ax mov es, ax xor ax, ax ; AX = 0x0000 mov cx, 1 int 0x31 ; allocate LDT descriptor jc @f2 mov [client_cs], ax xor ax, ax ; AX = 0x0000; mov cx, 1 ; already set above int 0x31 ; allocate LDT descriptor@f2: jcl 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 stubinfo_memory_handle[0], esi;* jmp got_dpmi_memorytry_old_dpmi_alloc: mov ax, 0x0501 mov bx, stubinfo_initial_size[2]; mov cx, stubinfo_initial_size[0] ;Set above int 0x31 ; allocate memory block jcl perror_no_dpmi_memory mov client_memory[2], bx mov client_memory[0], cx mov stubinfo_memory_handle[2], si mov stubinfo_memory_handle[0], digot_dpmi_memory: mov ax, 0x0007 mov bx, [client_cs] ; initialize client CS mov cx, client_memory[2] mov dx, client_memory[0] int 0x31 ; set segment base address mov ax, 0x0009; mov bx, [client_cs] ; already set above mov cx, cs ; get CPL and cx, 0x0003 shl cx, 5 push cx ; save shifted CPL for below or cx, 0xc09b ; 32-bit, big, code, non-conforming, readable int 0x31 ; set descriptor access rights mov ax, 0x0008; mov bx, [client_cs] ; already set above mov cx, stubinfo_initial_size[2] dec cx mov dx, 0xffff int 0x31 ; set segment limit mov ax, 0x0007 mov bx, [client_ds] ; initialize client DS mov cx, client_memory[2] mov dx, client_memory[0] int 0x31 ; set segment base address mov ax, 0x0009; mov bx, [client_ds] ; already set above pop cx ; shifted CPL from above or cx, 0xc093 ; 32-bit, big, data, r/w, expand-up int 0x31 ; set descriptor access rights mov ax, 0x0008; mov bx, [client_ds] ; already set above mov cx, stubinfo_initial_size[2] dec cx mov dx, 0xffff int 0x31 ; set segment limit;-----------------------------------------------------------------------------; Load the program data mov ax, 0x0100 mov bx, 0x0f00 ; 60K DOS block size int 0x31 ; allocate DOS memory jnc @f1 cmp ax, 0x0008 jnel perror_no_dos_memory mov ax, 0x0100 ; try again with new value in bx int 0x31 ; allocate DOS memory jcl 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, text_section[s_vaddr] mov ecx, text_section[s_size] call read_section mov esi, [data_foffset] ; load data section mov edi, data_section[s_vaddr] mov ecx, data_section[s_size] call read_section mov es, [client_ds] ; clear the BSS section mov edi, bss_section[s_vaddr] mov ecx, bss_section[s_size] xor eax,eax shr ecx,2 .addrsize rep stosd mov ah,0x3e mov bx, [program_file] int 0x21 ; close the file mov ax, 0x0101 mov dx, [dos_block_sel] int 0x31 ; free up the DOS memory push ds pop fs mov ds, [client_ds] .opsize jmpf fs:[start_eip] ; start program;-----------------------------------------------------------------------------; Read a section from the program fileread_section: mov eax, esi ; sector alignment by default and eax, 0x1ff 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 dpmi_regs[dr_dx], si ; store file offset shr esi, 16 mov dpmi_regs[dr_cx], si mov bx, [program_file] mov dpmi_regs[dr_bx], bx movw dpmi_regs[dr_ax], 0x4200 call pm_dos ; seek to start of data; Note, handle set above mov ax, [dos_block_seg] mov dpmi_regs[dr_ds], ax movw dpmi_regs[dr_dx], 0 ; store file offsetread_loop: movb dpmi_regs[dr_ah], 0x3f mov ax, read_size[2] ; see how many bytes to read or ax, ax jnz read_too_big mov ax, read_size[0] cmp ax, [dos_block_size] jna read_size_in_ax ; jna shorter than jmpread_too_big: mov ax, [dos_block_size]read_size_in_ax: mov dpmi_regs[dr_cx], ax call pm_dos ; read the next chunk of file data xor ecx, ecx mov cx, 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] .addrsize rep movsd pop es pop ds add ecx, [read_size] ; ecx zero from the rep movsd jnz read_loop ret;-----------------------------------------------------------------------------; Routine to check al for delimitertest_delim: cmp al, ':' ; watch for file name part je @f3 cmp al, '/' je @f3 cmp al, '\\'@f3: ret;-----------------------------------------------------------------------------; Copy string from environment to loadname.; On entry: di = environment offset; ah = termination character (null also does); On exit: bx = pointer to one character after last observed file delimiter; di = pointer to one character after last copied; si = pointer to the copied termination character; al = terminating characterstore_env_string: mov si, loadname ; pointer to buffer mov bx, si ; in case no delimiters@b1: mov al, es:[di] ; copy a character to buffer inc di mov [si], al cmp al, ah ; end of file name? je @f1 or al, al ; end of file name? je @f1 inc si call test_delim jne @b1 mov bx, si ; remember pointer to first char of je @b1 ; next name component (shorter than jmp)@f1: ret;-----------------------------------------------------------------------------; Most errors come here, early ones jump direct (8088 instructions)error_no_progfile: mov al, 102 mov dx, msg_no_progfile jmp error_fnerror_not_exe: mov al, 103 mov dx, msg_not_exe jmp error_fnerror_not_coff: mov al, 104 mov dx, msg_not_coff; jmp error_fnerror_fn: push dx mov bx, [loadname_nul] ; error, print file name movb [bx], '$' mov bx, loadname jmp @f1error_no_dos_memory_umb: call restore_umberror_no_dos_memory: mov al, 105 mov dx, msg_no_dos_memory jmp errorerror_in_modesw: mov al, 106 mov dx, msg_error_in_modesw jmp errorperror_no_selectors: mov al, 107 mov dx, msg_no_selectors jmp errorperror_no_dpmi_memory: mov al, 108 mov dx, msg_no_dpmi_memory jmp errorperror_no_dos_memory: mov al, 105 mov dx, msg_no_dos_memory; jmp errorerror: push dx mov bx, err_string@f1: call printstr pop bx call printstrexit: mov bx, crlfdollar call printstr mov ah, 0x4c ; error exit - exit code is in al
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -