📄 init.asm
字号:
com_wild_loop: mov al, bios_port_num
xor ah, ah
call set_port_ser
inc bios_port_num
loop com_wild_loop
jmp short c_get_port_ret
com_not_wild: call hex_number
call set_port_ser
jmp short c_get_port_ret
com_bad: pmsg m_com_bad
c_get_port_ret: ret
set_com_port ENDP
set_lpt_port PROC NEAR
call find_port_arg
jc lpt_bad
cmp al, ' '
jbe lpt_wild
cmp al, '*'
jne lpt_not_wild
lpt_wild: mov cl, num_lpt
xor ch, ch
jcxz l_get_port_ret
mov bios_port_num, 1
lpt_wild_loop: mov al, bios_port_num
xor ah, ah
call set_port_par
inc bios_port_num
loop lpt_wild_loop
jmp short l_get_port_ret
lpt_not_wild: call hex_number
call set_port_par
jmp short l_get_port_ret
lpt_bad: pmsg m_lpt_bad
l_get_port_ret: ret
set_lpt_port ENDP
hex_number PROC NEAR
; Input:
; ES:SI pointing at hexadecimal string
;
; Output:
; AX = binary value
;
xor ax, ax ; Clear accumulator
mov cl, 4
hex_loop: mov bl, es:[si] ; Get the next digit
cmp bl, '0' ; Check range
jb hex_done
cmp bl, 'a'
jb check_hex
sub bl, 'a' - 'A' ; Convert to upper case
check_hex: cmp bl, '9'
jbe is_digit
cmp bl, 'F'
ja hex_done
cmp bl, 'A'
jb hex_done
sub bl, '7'
jmp short add_digit
is_digit: sub bl, '0'
add_digit: shl ax, cl
or al, bl
inc si
jmp hex_loop
hex_done: ret
hex_number ENDP
decimal_number PROC NEAR
; Input:
; ES:SI pointing at decimal string
;
; Output:
; DX:AX = decimal value
;
; NOTE: This routine stops scanning after it overflows into DX. It can
; handle numbers as big as 655350 before it stops scanning.
;
xor ax, ax ; Clear accumulator
xor bx, bx
xor dx, dx
mov di, 10 ; Base 10 multiplier
decimal_loop: mov bl, es:[si] ; Get the next digit
cmp bl, '0' ; Check range
jb decimal_ret
cmp bl, '9'
ja decimal_ret
sub bl, '0' ; It's a digit, so normalize it
or dx, dx
jnz dec_overflow
mul di ; Multiply previous value by 10
add ax, bx ; Add in new 'ones' value
adc dx, 0
inc si
jmp decimal_loop
decimal_ret: clc
ret
dec_overflow: stc
ret
decimal_number ENDP
validate_port PROC NEAR
test ax, 3
jnz bad_port
cmp ax, 200H
jb bad_port
cmp ax, 8000H
jae bad_port
clc
jmp short vp_ret
bad_port: stc
vp_ret: ret
validate_port ENDP
set_port_ser PROC NEAR
push cx
or ax, ax
jz bad_ser_addr
cmp ax, 4
ja ser_do_set
cmp al, num_com
ja bad_bios_ser
mov bios_port_num, al
push es
mov bx, 40H
mov es, bx
dec ax
mov di, ax
shl di, 1 ; Serial table at 40:0
mov ax, es:[di]
pop es
ser_do_set: call validate_port
jc bad_ser_addr
xor bx, bx
mov cl, 0
walk_ser: cmp cl, num_ser_ports
jae new_ser
cmp ax, serial_ports[bx].SERIAL_PORT_DEF.sp_address
je set_port_ret ; Ignore duplicate address
inc cl
add bx, TYPE SERIAL_PORT_DEF
jmp walk_ser
new_ser: cmp num_ser_ports, MAX_SERIAL_PORTS
jae too_many_ser
mov serial_ports[bx].SERIAL_PORT_DEF.sp_address, ax
push es
push di
xor di, di
mov cx, 40H
mov es, cx
mov cl, num_com
xor ch, ch
repne scasw
mov ax, di
pop di
pop es
je save_ser_bios
xor ax, ax
save_ser_bios: shr al, 1
mov serial_ports[bx].SERIAL_PORT_DEF.sp_biosnum, al
inc num_ser_ports
inc num_ports
jmp short set_port_ret
bad_ser_addr: push ax
pmsg m_bad_ser_addr
jmp short show_hex_addr
bad_bios_ser: push ax
pmsg m_bad_bios_ser
jmp short show_hex_addr
too_many_ser: push ax
pmsg m_too_many_ser
show_hex_addr: pop ax
call show_hex
call show_crlf
set_port_ret: pop cx
ret
set_port_ser ENDP
set_port_par PROC NEAR
push cx
or ax, ax
jz bad_par_addr
cmp ax, 3
ja par_do_set
cmp al, num_lpt
ja bad_bios_par
mov bios_port_num, al
push es
mov bx, 40H
mov es, bx
dec ax
mov di, ax
shl di, 1 ; Serial table at 40:0
add di, 8 ; Parallel table at 40:8
mov ax, es:[di]
pop es
par_do_set: call validate_port
jc bad_par_addr
xor bx, bx
mov cl, 0
walk_par: cmp cl, num_par_ports
jae new_par
cmp ax, parallel_ports[bx].PARALLEL_PORT_DEF.pp_address
je par_sp_ret ; Ignore duplicate address
inc cl
add bx, TYPE PARALLEL_PORT_DEF
jmp walk_par
new_par: cmp num_par_ports, MAX_PARALLEL_PORTS
jae too_many_par
mov parallel_ports[bx].PARALLEL_PORT_DEF.pp_address, ax
push es
push di
mov di, 8
mov cx, 40H
mov es, cx
mov cl, num_lpt
xor ch, ch
repne scasw
mov ax, di
pop di
pop es
je save_par_bios
mov al, 8
save_par_bios: sub al, 8
shr al, 1
mov parallel_ports[bx].PARALLEL_PORT_DEF.pp_biosnum, al
inc num_par_ports
inc num_ports
jmp short par_sp_ret
bad_par_addr: push ax
pmsg m_bad_par_addr
jmp short show_hex_par
bad_bios_par: push ax
pmsg m_bad_bios_par
jmp short show_hex_par
too_many_par: push ax
pmsg m_too_many_par
show_hex_par: pop ax
call show_hex
call show_crlf
par_sp_ret: pop cx
ret
set_port_par ENDP
show_crlf PROC NEAR
pmsg cr_lf
ret
show_crlf ENDP
show_hex PROC NEAR
push bx
push cx
mov bx, 3
mov cl, 4
skip_zero_loop: test ah, 0F0H
jnz show_digits
rol ax, cl
dec bx
jnz skip_zero_loop
show_digits: inc bx
show_dig_loop: rol ax, cl
mov dl, al
and dl, 0FH
add dl, '0'
cmp dl, '9'
jbe show_dig
add dl, 7
show_dig: call show_char
dec bx
jnz show_dig_loop
pop cx
pop bx
ret
show_hex ENDP
show_address PROC NEAR
mov dl, '('
call show_char
call show_hex
mov dl, ')'
call show_char
ret
show_address ENDP
show_char PROC NEAR
PUBLIC show_char
push ax
mov ah, 2
int 21H
pop ax
ret
show_char ENDP
IFDEF DEBUG
wait_message db LF, "Hit any key to continue. . .$"
wait_for_key PROC NEAR
pmsg wait_message
mov ah, 08H ; Wait for any key
int 21H
call show_crlf
ret
wait_for_key ENDP
ENDIF
; get_max_secsize finds the largest allowable sector size on the MASTER
; system. Any device that has a sector size larger that max_secsize on the
; slave system cannot be used! This subroutine also determines the first
; unit number!
;
get_max_secsize PROC NEAR
mov ah, 52H ; Get DOS's list of lists
int 21H
; Use DOS 3.0+ offsets
mov ax, es:[bx + 10H] ; Max sector size
mov cl, es:[bx + 20H] ; First unit
mov max_secsize, ax
mov first_unit, cl
ret
get_max_secsize ENDP
read_timer PROC NEAR
pushf
cli
mov al, TIMER_0_LATCH
out TIMER_CTL, al ;Latch current count in 8253
jmp short $+2 ;Insure 5 clocks for 8253 recovery time
in al, TIMER_0 ;Get low order byte
mov ah, al ;Save it in AH
jmp short $+2 ;Insure 5 clocks for 8253 recovery time
in al, TIMER_0 ;Get high order byte
popf
ret
read_timer ENDP
; make_client_id gets an arbitrary non-zero number and places it in
; client_id. This value is used to identify this image of the device driver
; to the server system. If the ID's don't match in a SERVER_INFO exchange,
; the initialized flag will be cleared to force a re-initialization.
;
make_client_id PROC NEAR
push bx
push cx
push dx
push si
push es
mov si, 40H
mov es, si
xor si, si
mov cx, 64
; Build a 32-bit machine ID by XORing the first 64 DWORDS in the BIOS data
; area into DX:BX. Let DX:BX start with whatever happens to be in them at
; the time.
build_loop: lodsw
xor bx, ax
lodsw
xor dx, ax
loop build_loop
call read_timer ; Now XOR timer value into high word
xor bx, ax
call read_timer ; and again into low word
xor dx, ax
or bx, dx
jnz @F
inc bx ; insure != 0
@@: mov word ptr client_id, bx
mov word ptr client_id + 2, dx
pop es
pop si
pop dx
pop cx
pop bx
ret
make_client_id ENDP
init_end LABEL BYTE
INIT ENDS
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -