📄 ioisr.asm
字号:
add di, 2 ;past space and attribute
cmp di, VID_PAGE_SIZE
jb display_i100
xor di, di ;back to start of page
display_i100:
mov display_loc, di
pop es
pop ds
popa
ret
display_it endp
put_hex_digit proc near
push ax
mov cx, 2 ;2 digits in al
mov ah, al
put_hex_100:
shr al, 4
cmp al, 9
ja put_hex_200
add al, '0'
jmp short put_hex_300
put_hex_200:
add al, 'A' - 10
put_hex_300:
cld
stosb
inc di ;past attrib
mov al, ah
shl al, 4
loop put_hex_100
pop ax
ret
put_hex_digit endp
;--------------------------------------------------------------
;pass_thru - This procedure is JMPed to by any interrupt |
; handler which wishes to pass control to the |
; original ISR per the interrupt vector table. |
; |
; Entry: |
; See stack_area struc for stack layout |
; Any error code has been removed from stack.|
; EIP on stack has been adjusted if |
; necessary. |
;--------------------------------------------------------------
pass_thru proc near
mov bp, sp
pushad
push ds
mov ax, offset gdt_seg:sel_databs
mov ds, ax ;address all base memory
movzx ebx, [bp].s_ss ;user stack
shl ebx, 4 ;make linear
mov edx, [bp].s_esp ;user stack pointer
sub edx, 6 ;flags, cs, ip
mov [bp].s_esp, edx ;adjust it
mov eax, [bp].s_eflags ;put on flags
mov [ebx][edx].user_flags, ax
;
;change flags on stack so that original ISR will be entered with
;interrupts cleared and trap flag cleared to be consistent with their
;state upon entering an ISR (the normal way).
;
and ax, not (TRAP_FLAG + INT_FLAG)
mov [bp].s_eflags, eax ;put back flags
mov ax, [bp].s_cs ;put on user cs
mov [ebx][edx].user_cs, ax
mov eax, [bp].s_eip ;put on ip
mov [ebx][edx].user_ip, ax
movzx ebx, [bp].s_pushed_int ;get int number
movzx eax, [ebx * 4].d_offset ;offset portion
mov [bp].s_eip, eax
mov ax, [ebx * 4].d_segment ;segment portion
mov [bp].s_cs, ax
pop ds
popad
add sp, 2 ;get rid of int number
pop bp
iretd
pass_thru endp
;--------------------------------------------------------------
;gen_prot_isr - JMP here if int 0dh. Process as follows: |
; |
; Look for software int. If found, go route to |
; appropriate ISR. |
; |
; Look for I/O instructions we currently |
; support. If found, store port, size and |
; direction of I/O. Also, set trap flag and |
; return (we will get control at int 1 to |
; inspect data). |
; |
; If other than software int or I/O, go |
; display 0dh and halt. |
; |
;--------------------------------------------------------------
gen_prot_isr proc near
push ds
pushad
mov bx, offset gdt_seg:sel_databs
mov ds, bx
movzx ebx, [bp].e_cs ;get cs of user instruction
shl ebx, 4 ;make linear
add ebx, [bp].e_eip ;add ip
mov ax, [ebx] ;get bytes at cs:ip
cmp al, INT_OPCODE
jne get_prot100
inc [bp].e_eip ;get past the 0cdh
get_prot050:
inc [bp].e_eip
;
;Adjust stack so that error code goes away and int number retrieved from
;instruction goes in spot on stack where pushed int number is (for stacks
;with no error code). Stack will be the way pass_thru routine likes it.
;
mov bx, [bp].e_pushed_bp
shl ebx, 16 ;get into high word
mov bl, ah ;interrupt number
mov [bp].e_errcode, ebx
popad
pop ds
add sp, 4 ;error code gone
jmp pass_thru
get_prot100:
cmp al, INT3_OPCODE
jne get_prot150
mov ah, 3 ;interrupt 3
jmp short get_prot050
get_prot150:
mov bx, offset gdt_seg:sel_data
mov ds, bx
mov bx, offset io_table
mov cx, IO_TAB_ENTRIES
get_prot200:
cmp al, [bx].io_opcode
jne get_prot300
mov trap_status, EXPECT_INT1
mov cl, [bx].io_info ;get info about instruction
mov access_info, cl
test cl, CONSTANT ;is port number in instruction?
jz get_prot250 ;if not, we have it
xchg ah, al ;ah = 2nd byte of instruction
sub ah, ah
mov dx, ax
get_prot250:
mov access_port, dx ;save port
and cx, (AWORD OR ABYTE) ;number of bits
sub ah, ah ;indicate clear
call do_bit_map
popad
pop ds
or [bp].e_eflags, TRAP_FLAG ;single step i/o
add sp, 2 ;int number pushed
pop bp
add sp, 4 ;error code
iretd
get_prot300:
add bx, size io_struc ;advance to next table entry
loop get_prot200
mov ax, [bp].e_cs ;get cs of user instruction
call display_it
mov eax, [bp].e_eip ;add ip
call display_it
popad
pop ds
mov ax, [bp].e_pushed_int
jmp fatal_error
gen_prot_isr endp
;--------------------------------------------------------------
;do_bit_map - For the number of ports specified, clear/set |
; corresponding I/O permission map bits. |
; |
; Enter: Ah = 0 clear, ah = 1 set |
; dx = starting port |
; cx = number of ports |
; |
; All registers saved. |
;--------------------------------------------------------------
do_bit_map proc near
push ax
push bx
push cx
push dx
push ds
mov bx, offset gdt_seg:sel_tss_alias
mov ds, bx
assume ds:tss_seg
mov bx, t_iomap
push cx
mov cx, dx ;port
and cl, 7 ;get non byte boundary
mov al, 1 ;first bit position
shl al, cl ;get out corresponding bit
shr dx, 3 ;start_port/8
pop cx
add bx, dx ;starting offset in map
do_bit100:
or ah, ah
jnz do_bit200
mov dl, al
not dl
and byte ptr [bx], dl ;turn off permission bit
jmp short do_bit250
do_bit200:
or byte ptr [bx], al ;turn on permission bit
do_bit250:
rcl al, 1 ;next bit position
jnc do_bit300
inc bx
rcl al, 1
do_bit300:
loop do_bit100
pop ds
pop dx
pop cx
pop bx
pop ax
ret
do_bit_map endp
;--------------------------------------------------------------
;user_int_isr - return buffer address to caller. |
; |
; Exit: dx:bx= far ptr to io_buf |
; ah = total count of data wrap |
; al = buffer size (KB) |
; cx = offset of the start of data |
;--------------------------------------------------------------
user_int_isr proc near
mov dx, data
mov bx, offset data:io_buf
push ds
mov ds,dx
assume ds:data
mov cx, io_buf_ptr
mov ax, BUF_SIZE
shr ax, 10 ; size in KB
mov ah, io_buf_wrap
pop ds
iret
user_int_isr endp
isrcode ends
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -