Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- .386P
- ;; Segment descriptor structure
- descr struc
- lim dw 0
- base_l dw 0
- base_m db 0
- attr_1 db 0
- attr_2 db 0
- base_h db 0
- descr ends
- ;; Trap gate structure
- trap struc
- offs_l dw 0
- sel dw 16
- cntr db 0
- dtype db 8Fh
- offs_h dw 0
- trap ends
- data segment use16
- ;; Global descriptors table
- gdt_null descr <>
- gdt_data descr <data_size-1,,,92h>
- gdt_code descr <code_size-1,,,98h>
- gdt_stack descr <255,,,92h,,>
- gdt_screen descr <3999,8000h,0Bh,92h>
- gdt_size = $-gdt_null
- ;; IDT
- idt label word ;; label for exception table start
- trap 13 dup (<dummy>) ;; 0-12 exceptions
- trap <exc13> ;; exception 13
- trap 18 dup (<dummy>) ;; exceptions 14-31
- trap <new_08,,8Eh> ;; timer interrupt
- trap <new_09,,8Eh> ;; keyboard interrupt
- idt_size=$-idt ;; idt size label
- ;; Other data definition
- pdescr df 0 ;; Descriptor for lgdt and lidt
- sym db 1
- attr db 1Eh
- msg db 27,'We returned to real mode!',27,'$'
- master db 0
- slave db 0
- time dw 0
- delay_str db 30, ?, 30 dup('$')
- intsNum dw ?
- delay_prompt db "Set delay to: ", '$'
- data_size=$-gdt_null
- data ends
- ;; Command segment
- text segment use16
- assume CS:text, DS:data
- textseg label word
- exc13 proc
- pop eax
- pop eax
- iret
- exc13 endp
- dummy proc
- iret
- dummy endp
- new_08 proc
- push ax
- push bx
- push di
- inc edx
- cmp edx, 50
- jb continue_count ; Less than 50 hits
- second_dec:
- mov di, 40h ; start position to print remaining time
- mov edx, 0f200f20h ; overrride old value with spaces
- mov dword ptr es:[di], edx
- mov dword ptr es:[di+4], edx
- mov ax, time ; remaining time( in seconds )
- mov bx, 10 ; base
- call print_number
- dec time ; decrease remaining time
- mov edx, 0
- continue_count:
- mov al, 020h
- out 020h, al ;; 20h - > master
- out 0A0h, al ;; 20h -> slave
- pop di
- pop bx
- pop ax
- iretd
- new_08 endp
- new_09 proc
- push ax
- in al, 60h
- in al, 61h
- or al, 80h
- out 61h, al
- and al, 7Fh
- out 61h, al
- mov al, 20h
- out 20h, al
- pop ax
- ;;db 66h
- iretd
- new_09 endp
- ;;---------------------
- ;; SI - string address
- ;; BL - number base
- ;; CL - string len
- ;; AX - result
- ;; BP - error code
- ;; -------------------
- to_number proc near
- push si
- push bx
- push dx
- push cx
- xor bh, bh
- xor ax, ax
- xor bp, bp
- xor dh, dh
- xor ch, ch
- next_char:
- mul bx ; dx:ax=ax*bx
- jb error_ ; Overflow means error
- mov dl,[si] ; Get next number
- cmp dl,48 ; Less than 48 is not number
- jb error_
- cmp dl,71 ; Letter bigger "F"
- jae testLittle ; Lowercase a-f letters checking
- jmp test_ ; 0-9 digits and A-F letters checking
- testLittle:
- cmp dl,97
- jb error_
- cmp dl,103
- jae error_
- jmp m_ab
- test_:
- cmp dl,58 ;; Less than 58 means 0-9 digits
- jb m_1
- cmp dl,65 ;; Bigger than 65 means A-F letters
- jae m_A
- ;; Value between 58 and 64 prohibited
- error_:
- mov ax,0 ;; Zero is error
- mov bp,1
- jmp to_exit
- m_1:
- sub dl,48
- jmp next_
- m_A:
- sub dl,55
- jmp next_
- m_ab:
- sub dl,87
- next_:
- cmp dl,bl ;; Next number in dl, base in bl
- jae error_ ;; number bigger than base
- add ax,dx
- jb error_ ;; overflow means error
- inc si
- loop next_char
- to_exit:
- pop cx
- pop dx
- pop bx
- pop si
- ret
- to_number endp
- ;; -------------
- ;; AX - target number
- ;; -------------
- print_number proc
- push cx
- push dx
- push ax
- xor cx,cx
- again2:
- sub dx,dx
- div bx ; ax/bx, remainder in dx
- inc cx ; Count digits
- push dx
- cmp ax,0
- jne again2 ; While number not zero
- toBuffer:
- pop dx ; Get digit from stack
- add dx,30h ; Add 30h to get its ASCII code
- mov dh, 00001110b ;; color code
- mov word ptr es:[di], dx
- add di, 2
- loop toBuffer
- pop ax
- pop dx
- pop cx
- ret
- print_number endp
- ;; Init timer
- timer_init proc near
- push ax
- mov al, 00110110b
- out 43h, al
- mov ax, 05D2Eh ;; set 50Hz frequence
- out 40h, al
- shr ax, 8
- out 40h, al
- pop ax
- ret
- timer_init ENDP
- enter_delay proc near
- push ax
- push dx
- push si
- push bx
- push cx
- ;; Clear screen
- mov ax,3
- int 10h
- ;;
- lea dx, delay_prompt
- mov ah, 09h
- int 21h
- lea dx, delay_str;
- mov ah,0Ah
- int 21h
- mov si, offset delay_str+2
- mov bl, 10
- mov cl, delay_str[1]
- call to_number
- mov time, ax
- ;; Clear screen
- mov ax,3
- int 10h
- ;;
- pop cx
- pop bx
- pop SI
- pop dx
- pop ax
- ret
- enter_delay endp
- load_gdt_addr proc near
- shl eax, 4
- mov [bx].base_l, ax
- shr eax, 16
- mov [bx].base_m, al
- ret
- load_gdt_addr endp
- save_mask proc near
- push ax
- in al, 21h
- mov master, al
- in al, 0A1h
- mov slave, al
- pop ax
- ret
- save_mask endp
- init_master proc near
- mov al, 11h
- out 20h, al
- mov al, dl
- out 21h, al
- mov al, 4
- out 21h, al
- mov al, 1
- out 21h, al
- ret
- init_master endp
- init_segments_pr proc near
- ;; Make data available
- mov ax, 8
- mov ds, ax
- ;; Make stack available
- mov ax, 24
- mov ss, ax
- ;; Initialize ES
- mov ax, 32
- mov es, ax
- ret
- init_segments_pr endp
- return_masks proc near
- push ax
- mov al, master
- out 21h, al
- mov al, slave
- out 0A1h, al
- pop ax
- ret
- return_masks endp
- ;; --------------------------------------------------------
- ;; --------------------------------------------------------
- main proc
- xor eax, eax
- mov ax, data
- mov ds, ax
- call timer_init
- call enter_delay
- shl eax, 4
- mov ebp, eax
- ;; Calculate and load in GDT linear address of data segment
- mov ax, data
- mov bx, offset gdt_data
- call load_gdt_addr
- ;; Calculate and load in GDT linear address of command segment
- xor eax, eax
- mov ax, cs
- mov bx, offset gdt_code
- call load_gdt_addr
- ;; Calculate and load in GDT linear address of stack segment
- xor eax, eax
- mov ax, ss
- mov bx, offset gdt_stack
- call load_gdt_addr
- ;; Prepare pdescr and load GDTR
- mov dword ptr pdescr+2, ebp ;; GDT base
- mov word ptr pdescr, gdt_size-1
- lgdt pdescr ;; load GDTR
- cli
- ;; Save interrupt masks
- call save_mask
- ;; init master ( base vector now 32)
- push dx
- mov dl, 32
- call init_master
- pop dx
- mov al, 0FCh ;; New mask
- out 21h, al
- ;; LOad IDTR
- mov word ptr pdescr, idt_size-1
- xor eax, eax
- mov ax, offset idt
- add eax, ebp ;; IDT linear address
- mov dword ptr pdescr+2, eax
- lidt pdescr
- ;; Switch mode to protected
- mov eax, cr0
- or eax, 1 ;; set protected mode bit
- mov cr0, eax
- ;; Now in protected mode
- ;; Load in CS:IP address of 'continue' label
- db 0EAh
- dw offset continue
- dw 16
- continue:
- call init_segments_pr
- home:
- xor ecx, ecx
- sti
- wait_: ;; wait for delay end
- cmp time, -1
- jne wait_
- toRealMode:
- ;; Return to real mode
- cli
- ;; Made and load descriptors for real mode
- mov gdt_data.lim, 0FFFFh
- mov gdt_code.lim, 0FFFFh
- mov gdt_stack.lim, 0FFFFh
- mov gdt_screen.lim, 0FFFFh
- push ds ;; data segment register
- pop ds
- push ss ;; load stack segment register
- pop ss
- push es ;; load extended segment register
- pop es
- ;; Do far jmp
- db 0EAh
- dw offset go
- dw 16
- go:
- ;; Switch processor mode
- mov eax, cr0
- and eax, 0FFFFFFFEh
- mov cr0, eax
- ;; Do far jmp to return label
- db 0eah
- dw offset return
- dw text
- ;; Now in real mode
- return:
- mov ax, data
- mov ds, ax
- mov ax, stk
- mov ss, ax
- mov sp, 256
- ;; Reload state of IDTR
- mov ax, 3FFh
- mov word ptr pdescr, ax
- mov eax, 0
- mov dword ptr pdescr+2, eax
- lidt pdescr
- sti
- ;; Reinit master PIC and set base vector 08h
- push dx
- mov dl, 8
- call init_master
- pop dx
- ;; Return mask for master and slave
- call return_masks
- sti
- ;; Write msg
- mov ah, 09h
- mov dx, offset msg
- int 21h
- mov ax, 4c00h
- int 21h
- main endp
- code_size=$-textseg
- text ends
- stk segment stack use16
- db 256 dup('^')
- stk ends
- end main
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement