📄 loader.asm
字号:
and si,0Fh
add si,si
mov _err_code,4006h ; "16bit fixup overflow"
call fix_tab[si]
pop si
jmp @@5
;
; EAX = Data
; EDX = Address of Object
; EDI = Address to Fixup
; EBP:EBX = Ptr to Current Object Table
;-----------------------------------------------------------------------------
fix_byte:
mov gs:[edi+0],al
ret
fix_16off:
mov gs:[edi+0],ax
ret
fix_32off:
add eax,edx
mov gs:[edi+0],eax
ret
fix_32selfrel:
add eax,edx
lea ecx,[edi+4]
sub eax,ecx
test word ptr [ebp+ebx+12],2000h
jnz @@1
lea ecx,[eax+8002h]
shr ecx,16
jnz file_errorm
mov gs:[edi+0],ax
ret
@@1: mov gs:[edi+0],eax
ret
fix_16sel:
call check_range
mov gs:[edi+0],dx
ret
fix_1616ptr:
call check_range
mov gs:[edi+0],ax
mov gs:[edi+2],dx
ret
fix_1632ptr:
add eax,edx
mov gs:[edi+0],eax
call check_range
mov gs:[edi+4],dx
ret
fix_invalid:
mov ax,4005h ; "unrecognized fixup data"
jmp file_error
check_range:
test word ptr [ebp+ebx+12],1000h ; check if 16:16 alias requird
jnz @@1 ; if yes, jump
test cl,10h
jnz @@1
@@0: mov ecx,_app_tmp_addr2
mov dx,[ebp+ecx+14] ; get selector
ret
@@1: test cl,10h
jz @@0
mov ecx,_app_tmp_addr2
mov dx,[ebp+ecx+14] ; get selector
test eax,0FFFF0000h ; check 64K range
jnz file_errorm
ret
evendata
fix_tab label word
dw fix_byte ; 00h
dw fix_invalid ; 01h
dw fix_16sel ; 02h
dw fix_1616ptr ; 03h
dw fix_invalid ; 04h
dw fix_16off ; 05h
dw fix_1632ptr ; 06h
dw fix_32off ; 07h
dw fix_32selfrel ; 08h
;-----------------------------------------------------------------------------
; In: ECX = size
; Out: EDI = address
;
fill_zero_pages:
push es dx eax ecx edi
push gs
pop es
mov dl,cl
shr ecx,2
xor eax,eax
rep stos dword ptr es:[edi]
mov cl,dl
and cl,3
rep stos byte ptr es:[edi]
pop edi ecx eax dx es
ret
;-----------------------------------------------------------------------------
; In: EAX = size
; Out: EDI = address
;
alloc_block:
push dx
test eax,eax ; if size of Object is zero
jz @@null ; then report a warning 9005
mov dl,_misc_byte ; get misc byte
shr dx,4 ; get memory alloc bits in bit1,0
and dx,3 ; mask them
jz @@00 ; if 00b alloc scheme, jump
dec dx
jz @@01
dec dx
jz @@10
dec dx
jz @@11
@@done: pop dx
ret
@@null: push ax si
mov si,[esp+0Ch]
mov ax,9005h
call report_error
pop si ax dx
xor edi,edi
ret
;
; load 16bit/32bit -> low, then high, then error
;---------------------------------------
@@00: call alloc_dos_mem ; try to allocate DOS memory block
jnc @@done ; if allocated, jump
mov _err_code,4003h ; "not enough DPMI mem"
call alloc_dpmi_mem ; try to allocate DPMI memory block
jnc @@done ; if allocated, jump
jmp file_errorm ; if failed, error
;
; load 16bit -> low, then high, then error
; load 32bit -> high only, then error
;---------------------------------------
@@01: test cx,2000h ; check if 32bit Object
jnz @@01_1 ; if yes, jump
mov _err_code,4002h ; "not enough DOS mem"
call alloc_dos_mem
jnc @@done ; if allocated, jump
@@01_1: mov _err_code,4003h ; "not enough DPMI mem"
call alloc_dpmi_mem
jnc @@done ; if allocated, jump
jmp file_errorm ; if failed, error
;
; load 16bit/32bit low, then error
;---------------------------------------
@@10: mov _err_code,4002h ; "not enough DOS mem"
call alloc_dos_mem
jnc @@done
jmp file_errorm ; if failed, error
;
; load 16bit/32bit high, then error
;---------------------------------------
@@11: mov _err_code,4003h ; "not enough DPMI mem"
call alloc_dpmi_mem
jnc @@done
jmp file_errorm ; if failed, error
;-----------------------------------------------------------------------------
alloc_dos_mem:
push eax ebp ; EAX = size to allocate
add eax,0Fh ; align size on para
shr eax,4
test eax,0FFFF0000h ; check high word of EAX
stc
jnz @@done
sub esp,32h
mov ebp,esp
mov byte ptr [ebp+1Dh],48h ; DOS func: AH=48h
mov word ptr [ebp+10h],ax ; DOS BX=size
call int21h
movzx edi,word ptr [ebp+1Ch] ; get returned value in EAX
shl edi,4 ; NOTE: addres is relative to 0
bt word ptr [ebp+20h],0 ; check for errors
lea esp,[esp+32h]
@@done: pop ebp eax
ret
;-----------------------------------------------------------------------------
alloc_dpmi_mem:
push esi ebx ecx edx eax
mov ebx,eax
mov ax,0FF91h ; allocate DPMI memory
int 21h
jc @@done
mov eax,ebx
xor edx,edx
test _misc_byte2,00000100b ; check if para or page alignment
jnz @@l1
test al,0Fh
jz @@1
jmp @@l2
@@l1: test ax,0FFFh ; check if returned addr aligned
jz @@1 ; on PAGE boundary, if yes, jump
@@l2: test _misc_byte2,00000100b
jnz @@l3
add ebx,0Fh
and bl,0F0h
jmp @@l4
@@l3: add ebx,0FFFh
and bx,0F000h ; align linear addr on PAGE boundary
@@l4: sub ebx,eax ; calculate difference
mov edx,ebx
add ebx,[esp]
mov ax,0FF93h ; resize DPMI memory block
int 21h
jc @@done
@@1: lea edi,[ebx+edx] ; adjust linear address
test _misc_byte2,00000100b
jnz @@l5
test di,000Fh
jmp @@l6
@@l5: test di,0FFFh
@@l6: stc
jnz @@done
clc
@@done: pop eax edx ecx ebx esi
ret
;-----------------------------------------------------------------------------
create_selector:
push ebx ecx edx esi edi
mov ax,dx
mov ecx,ebp ; ECX = Virtual Size[Object]
mov dx,_acc_rights ; default: PAGE, USE32, DATA
test al,0004h ; check if object is executable
jz @@1 ; if not, jump
or dl,0008h ; set selector to Code
@@1: test ax,2000h ; check if object is 32bit
jz @@2 ; if not, jump
xor edi,edi ; set base to Zero
or ecx,-1 ; set limit to 4Gb
test al,0004h ; check if code or data Object
mov ax,_sel32_cs ; AX = 32bit code selector
jnz @@0 ; if code, then jump
mov ax,_sel32_ss ; AX = 32bit data selector
@@0: test ax,ax ; check if already allocated
jnz @@4 ; if yes, use this selector
jmp @@3
@@2: and dx,0BFFFh ; set selector to 16bit
@@3: call set_descriptor ; allocate selector
jc dpmi_error
@@4: pop edi esi
mov [esp+2],ax ; store selector in high word of EDX
pop edx ecx ebx
mov _app_buf_allocsel[ecx*2],ax
mov _app_buf_allocbase[ecx*4],edi
cmp cx,word ptr _app_eip_object; is Current_Object# == EIP_Object#
jnz @@l1 ; if not, jump
mov _sel32_cs,ax
mov _unreloc_eip,edi
test dx,2000h ; check if Object is 32bit
jz @@l1 ; if not, leave _APP_EIP as is
add _app_eip,edi
@@l1: cmp cx,word ptr _app_esp_object; is Current_Object# == ESP_Object#
jnz @@l2 ; if not, jump
mov _sel32_ss,ax
mov _unreloc_esp,edi
add _app_esp,edi ; adjust ESP
@@l2: ret
preload_fixups:
cmp _app_type,2
jz preload_lc_fixups
mov ebx,_app_siz_fixrecstab ; allocate memory for fixups
mov _app_load,0 ; default load fixups low
mov ax,0FF95h
int 21h
jnc @@1
mov _app_load,1 ; try load fixups hi
mov al,91h
int 21h
mov ax,4004h
jc file_error ; if not enough memory, error
@@1: mov _app_buf_fixrecstab,esi
mov _err_code,3002h ; "error in app file"
mov edx,_app_off_fixpagetab ; move file ptr to fixups
call seek_from_start
mov edx,ebx
mov ecx,_app_siz_fixrecstab
call load_gs_block
mov eax,_app_off_fixrectab
mov ebx,_app_off_fixpagetab
sub eax,ebx
add eax,edx
mov _app_off_fixpagetab,edx
mov _app_off_fixrectab,eax
ret
unload_fixups:
cmp _app_type,2
jz unload_lc_fixups
mov esi,_app_buf_fixrecstab
mov ax,0FF96h
cmp _app_load,0
jz @@1
mov al,92h
@@1: int 21h
ret
PopState
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -