Chinaunix首页 | 论坛 | 博客
  • 博客访问: 178074
  • 博文数量: 69
  • 博客积分: 2627
  • 博客等级: 少校
  • 技术积分: 715
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-24 22:37
文章分类

全部博文(69)

文章存档

2017年(3)

2014年(1)

2013年(4)

2012年(6)

2011年(21)

2010年(15)

2009年(19)

我的朋友

分类: LINUX

2011-09-04 18:06:24

说明:icw2设置8259的irq0(timer)为0x20,则0x21(irq1)为keyboard.
nasm编译.

[section .text]
[org 0x100]
[bits 16]

start:
    xor eax,eax
    mov ax,cs
    shl eax,4
    mov ebx,eax

    mov [gdt1+2],ax
    mov [gdt2+2],ax
    shr eax,16
    mov [gdt1+4],al
    mov [gdt2+4],al
    mov [gdt1+7],ah
    mov [gdt2+7],ah

    lea eax,[ebx+gdt]
    mov [gdtr+2],eax

    lea eax,[ebx+idt]
    mov [idtr+2],eax

    cli

    lgdt [gdtr]
    lidt [idtr]


    mov eax,cr0
    or al,1
    mov cr0,eax

    jmp SYS_CODE_SEL:do_pm

[bits 32]
do_pm:
    mov ax,VIDEO_SEL
    mov gs,ax

    mov ax,SYS_DATA_SEL
    mov ds,ax

    mov byte [gs:(8 * 80 + 10) * 2],'P'

    mov byte [gs:(10 * 80 + 10) * 2],'A'

;等输出缓冲区
kbWrite:
WaitLoop:    in     al, 0x64     ; Read Status byte
             and    al, 0x01     ; Test OBF flag (Status<0>)
             jnz    WaitLoop    ; Wait for OBF = 0
             ;out    60h, cl     ; Write data to output buffer

    mov byte [gs:(10 * 80 + 60) * 2],'O'
    mov byte [gs:(10 * 80 + 61) * 2],'K'

    ;向键盘发送command byte,使其可以产生中断
    
    
;    mov al,0x60
;    out 0x64,al
;    mov al,0xf6
;    out 0x60,al
;    mov al,0x60
;    out 0x64,al
;    mov al,0xf4
;    out 0x60,al

    mov al,0x60
    out 0x64,al
    mov al,0x41
    out 0x60,al
    
    mov byte [gs:(20 * 80 + 50 ) * 2],'A'
    mov byte [gs:(20 * 80 + 60 ) * 2],'A'

    mov byte [gs:(10 * 80 + 65) * 2],'o'
    mov byte [gs:(10 * 80 + 66) * 2],'k'

    call init8259A
    
    int 0x80    ; display 'S'

    sti             ; 打开中断,以产生时钟中断

    jmp $


init8259A:                   ; 先写0x20端口,然后是0xA0,再然后是三个0x21,0xA1
    mov al,0x11          ; need icw4,级联,8字节中断向量,边缘触发,
    out 0x20,al
    call io_delay
    
    out 0xA0,al          ;
    call io_delay

    mov al,0x20          ; icw2,低3位全0:80x86, 3-7位中断向量 ,icw2设置主,从8259A的第一个中断对应的向量号,irq0对应0x20
    out 0x21,al          ; 高5位称为中断类型码,是中断向量的高5位,低3位由引脚决定
    call io_delay

    mov al,0x28          ; 0x28 = 0010 1000 , irq8(从片第一个) 对应0x28,
    out 0xA1,al
    call io_delay

    mov al,0x04          ; 主片icw3,  第2位为1,表示第2(从0开始)个引脚挂从片
    out 0x21,al
    call io_delay

    mov al,0x02          ; 从片icw3, 低3位表示连的是主片的哪个引脚
    out 0xA1,al
    call io_delay

    mov al,0x01          ; icw4, 第0位表示80x86
    out 0x21,al
    call io_delay

    out 0xA1,al
    call io_delay

    mov al,0xFD          ; 打开时钟,键盘,其余屏掉      
    out 0x21,al
    call io_delay

    mov al,0xFF          ; 从片屏掉
    out 0xA1,al
    call io_delay

    ret

io_delay:
    nop
    nop
    nop
    nop
    ret

unhand:
    push ax
    push gs
    mov ax,VIDEO_SEL
    mov gs,ax
    mov byte [gs:(6 * 80 + 10) * 2],'H'
    pop gs
    pop ax

    iret

clock_timer:                ; display green A - Z
    pusha
    push gs
    
    mov ax,VIDEO_SEL
    mov gs,ax
    
    mov byte [gs:((10 * 80 + 10) * 2 + 1)],0x1e  ; color
    inc byte [gs:(10 * 80 + 10) * 2]
    
    mov al,[gs:(10 * 80 + 10) * 2]
    cmp al,0x5C      ; 'Z'+1
    jne .1
    mov byte [gs:(10 * 80 + 10) * 2],0x41
.1        
    
;    mov ecx,0x0fffffff  ;only for delay
;.2    mov dx,0xffff  
;    mov ax,0x17  
;    mul ax
;    mov dx,0xffff  
;    mov ax,0x17  
;    mul ax
    

;    dec ecx
;    cmp ecx,0
;    ja  .2
    
    call io_delay

    mov al,0x20
    out 0x20,al

    pop gs
    popa

    iretd   ; iret too

keyboard_interrupt:
    push eax
    push ebx
    push gs
    
    mov ax,VIDEO_SEL
    mov gs,ax

    inc byte [gs:(20 * 80 + 50 ) * 2]
    
        in  al,0x60
    mov bl,al          ;; temp store
    and al,0x80
    jz  break_code
    
    mov al, bl
    and al,0x7f
    mov si, ax
    ;cmp al,0xd
    ;jnz break_code

    mov al, byte [ds:(key_map+si)]

    mov byte [gs:(20 * 80 + 30 ) * 2],al
break_code:
 
    mov al,0x20
    out 0x20,al

    pop gs
    pop ebx
    pop eax

    iretd

user_handler:
    push ax
    push gs
    mov ax,VIDEO_SEL
    mov gs,ax
    mov byte [gs:(12 * 80 + 10) * 2],'S'
    pop gs
    pop ax

    iret  ; iretd too

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; DATA
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;[section .data]
align 32

data_seg:
char:   db 0x41,0xC
pos:    dd 0
gdtr:    dw gdt_end - gdt - 1
    dd 0

idtr:    dw idt_end - idt - 1
    dd 0

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;; GDT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 32

gdt:
    dw 0
    dw 0
    dw 0
    dw 0

SYS_CODE_SEL equ $ - gdt
gdt1:    dw 0xFFFF
    dw 0
    db 0
    db 0x9A
    db 0xCF
    db 0
SYS_DATA_SEL equ $ - gdt
gdt2:    dw 0xFFFF
    dw 0
    db 0
    db 0x92
    db 0xCF
    db 0

VIDEO_SEL equ $ - gdt
    dw 0xFFFF
    dw 0x8000
    db 0x0b
    db 0x92
    db 0xCF
    db 0

gdt_end:


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; IDT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
idt:
%rep 32                        ; 0 - 31
    dw unhand
    dw SYS_CODE_SEL
    db 0
    db 0x8E
    dw 0
%endrep

.020h:    dw clock_timer          ; 32          
    dw SYS_CODE_SEL                          ; SYS_CODE_SEL指向GDT中的代码段描述符,描述符没有offset。 GDT表项的base+IDT的offset才是最终的目标的地址.
    db 0
    db 0x8E
    dw 0

.021h:    dw keyboard_interrupt   ; 33          
    dw SYS_CODE_SEL             
    db 0
    db 0x8E
    dw 0


%rep 94                         ; 34 - 127
    dw unhand
    dw SYS_CODE_SEL
    db 0
    db 0x8E
    dw 0
%endrep

.080h:                         ; 128
    dw user_handler
    dw SYS_CODE_SEL
    db 0
    db 0x8E
    dw 0
idt_end:


; 中断0-19系统定义 20-31 intel保留,32-255自定义,本程序将主片irq0设为0x20, 从片irq0(irq8)设为0x28
; 并且只打开主片的irq0(时钟中断)
; 中断门寻址: 8259A产生中断irqx,根据icw2找到irqx在idt中的索引号,
; 从IDT中按索引号取出此中断门描述符里的selector,再根据这个selector找到gdt中的代码段描述符,
; 从gdt里取出的代码段描述符里,再取代码段的基地址,加上中断门描述符里的偏移,就是最终的代码入口。

align 2

key_buffer: db 0,0,0,0

key_map:
    db 0
    db 0
    db '1'       ;0x2
    db '2'
    db '3'
    db '4'
    db '5'
    db '6'
    db '7'
    db '8'
    db '9'
    db '0'
    db '-'
    db '='       ;0xd

阅读(1255) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~