Assembly2010. 1. 5. 01:46




.286
.model huge, stdcall  ; meomory and calling convation
option casemap :none  ; case sensitive


include MyMacro.inc


QUEUE_MAX_BUFFER    EQU    4    ; 최대 큐 버퍼 사이즈

init_serial proto near
EnQueue proto :byte
DeQueue proto


;-----------------------------------------------------------
SgIntVact   segment at 0
    org   30h
    V_Com1VactOfs   dw  ?
    V_Com1VactSeg   dw  ?
SgIntVact   ends

;-----------------------------------------------------------
SgBiosData  segment at 40h
    org   0

    V_Com1Port  dw  ?
    V_Com2Port  dw  ?

SgBiosData  ends
;-----------------------------------------------------------
data    segment
    V_OldComVactOfs dw  ?
    V_OldComVactSeg dw  ?

    V_ComDataPort       dw  ?
    V_ComIntEnablePort  dw  ?
    V_ComIntStatPort    dw  ?
    V_ComLineCtrlPort   dw  ?
    V_ComModemCtrlPort  dw  ?
    V_ComLineStatPort   dw  ?
    V_ComModemStatPort  dw  ?

    V_InputChar db  ?
   
    Queue    db  4 dup(0)    ; 실제 큐
    QueueSize    db  0        ; 큐 사용량
    TempPos    db  0        ; 가상 인덱스
    Position    db  0        ; 실제 인덱스

data    ends

stackseg segment stack
        db      100h    dup('stack')
stackseg ends

;-----------------------------------------------------------
code    segment
  ;-----------------------------------------------------------
  main  proc  far
        invoke init_serial  ;serial port initialize

        ;set segment
        assume  cs:code,ds:data
        mov   ax , data
        mov   ds , ax

        ;input loop
        mov   V_InputChar , 0
        .while  V_InputChar != '@'
          mov   ah , 06h
          mov   dl , 0FFh
          int   21h
          .if !zero?
            mov   V_InputChar , al
            ;send to serial
            mov   dx , V_ComDataPort
            out   dx , al
          .endif
     
      ;큐에서 꺼내 출력하기
      .if QueueSize == 4
        mov cx, 4
          CharLoop:
        invoke DeQueue
        mov ah, 2
        int 21h
        loop CharLoop
      .endif
        .endw

        ;serial off
        cli
        in    al , 21h    ;interupt off
        or    al , 10h
        out   21h , al
        ;restore interupt vactor
        assume  es:SgIntVact
        mov   ax , SgIntVact
        mov   es , ax

        mov   ax , V_OldComVactOfs
        mov   cx , V_OldComVactSeg
        mov   V_Com1VactOfs , ax
        mov   V_Com1VactSeg , cx
        sti

        ;serial reset
        mov   dx , V_ComIntEnablePort
        xor   ax , ax
        out   dx , al
        mov   dx , V_ComModemCtrlPort
        out   dx , al

        ;exist
        mov   ah , 4Ch
        int   21h

  main  endp
  ;-----------------------------------------------------------
  init_serial proc near
        ;com 1 initialize
        ;set interupt handler

        ;set segment
        assume  cs:code,ds:data,es:SgIntVact
        mov   ax , data
        mov   cx , SgIntVact
        mov   ds , ax
        mov   es , cx

        ;backup old interupt vactor
        mov   ax , V_Com1VactOfs
        mov   cx , V_Com1VactSeg
        mov   V_OldComVactOfs , ax
        mov   V_OldComVactOfs , cx
        ;set interupt vactor
        cli
        mov   ax , offset Irq_Serial
        mov   cx , cs
        mov   V_Com1VactOfs , ax
        mov   V_Com1VactSeg , cx
        ;set interupt mask
        in    al , 21h
        and   al , 0EFh
        out   21h , al
        sti
        ;serial prot initialize
        assume  es:SgBiosData   ;segment set
        mov   ax , SgBiosData
        mov   es , ax

        ;set com port set
        mov   ax , V_Com1Port
        mov   bx , offset V_ComDataPort
        mov   cx , 7
        .repeat
          mov   word ptr ds:[bx] , ax
          add   bx , 2    ;next register pointer
          inc   ax        ;next port address
        .untilcxz

        ;set boud rate , parrity , data length , stop bit
        mov   dx , V_ComLineCtrlPort
        mov   al , 83h    ;boud rate setting and none parrity ,
        out   dx , al     ;1 stop bit , 8bit data
        mov   dx , V_ComDataPort
        mov   al , 0Ch    ;9600 bps
        out   dx , al
        mov   dx , V_ComIntEnablePort
        xor   ax , ax
        out   dx , al

        ;set interupt
        mov   dx , V_ComLineCtrlPort
        mov   al , 3
        out   dx , al   ;data io mode
        mov   dx , V_ComIntEnablePort
        mov   al , 1    ; data receved only
        out   dx , al

        ;set  modem controler
        mov   dx , V_ComModemCtrlPort
        mov   al , 1011b    ;enable interupt and RTS,DTR
        out   dx , al

        ret

  init_serial endp
  ;-----------------------------------------------------------
  Irq_Serial  proc far
        ;protect register
        push  ax
        push  dx
        push  ds
        ;set segment
        assume  ds:data
        mov   ax , data
        mov   ds , ax
        ;when recive do set input charactor
        mov   dx , V_ComIntStatPort
        in    al , dx
        .if al & 100b    ;interupt generate and recive data?
          ;set data
          mov   dx , V_ComDataPort
          in    al , dx
          invoke EnQueue, al
        .endif
        ;set EOI
        mov   al , 20h
        out   20h , al
        ;restore register
        pop   ds
        pop   dx
        pop   ax

        iret

  Irq_Serial  endp

  EnQueue PROC MyValue:BYTE
    pusha
   
    assume ds:data       
    mov ax, data        ;
    mov ds, ax            ; 데이터 세그먼트 설정


    cmp QueueSize, QUEUE_MAX_BUFFER    ; 현재버퍼크기 >= 최대버퍼크기
    jge LABEL_BufferFull        ; 버퍼가 꽉 찻으므로 종료

    cmp Position, QUEUE_MAX_BUFFER    ;
    jl  LABEL_PositionNext        ; 데이터인덱스 < 최대버퍼크기
    mov Position, 0            ; Postion = 0

    LABEL_PositionNext:
    mov ah, Position        ;----------------------------------
    mov al, QueueSize        ; TempPos = Position + QueueSize
    add ah, al            ;
    mov TempPos, ah            ;----------------------------------

    cmp TempPos, QUEUE_MAX_BUFFER    ;
    jl  LABEL_TempPosChange        ; TempPos < 최대버퍼크기
    sub TempPos, QUEUE_MAX_BUFFER    ; TempPos = TempPos - 최대버퍼크기

    LABEL_TempPosChange:
    mov ah, MyValue            ;----------------------------------        
    xor bx, bx            ; 지정된 위치에 데이터 넣기
    mov bl, byte ptr TempPos    ;
    mov Queue[bx], ah        ;----------------------------------
       
    inc QueueSize            ; 현재버퍼크기 1 증가
    LABEL_Exit:
   

    popa
    ret

    LABEL_BufferFull:
       
    ;버퍼가 가득 차면 현재큐내용을 보여주고 초기화
    ShowAllQueueDebugString

    mov QueueSize, 0
    mov TempPos, 0
    mov Position, 0

    NextLine
            ;
       
    popa
    ret
    EnQueue ENDP


    ;-------------------------------------------------------------------
    ;
    ;    큐에서 값 하나를 꺼낸다.
    ;   
    ;    인자 :
    ;    리턴 : DL -> 큐에서 꺼낸 값
    ;
    ;-------------------------------------------------------------------
    DeQueue PROC
    push ax                ;-----------------------------
    push ds                ; 레지스터 보호
    push bx                ; ax, ds, bx, si, cx
    push si                ;
    push cx                ;-----------------------------
       
    assume ds:data           
    mov ax, data        ;
    mov ds, ax            ; 데이터 세그먼트 초기화
       
    cmp QueueSize, 0        ;
    jz  LABEL_BufferEmpty        ; 큐에 내용이 없으면 Buffer UnderFlow

    xor bx, bx            ;
    mov bl, byte ptr Position    ; 가져 올 값의 인덱스 구하기 -> BL
               

   
       
    mov dl, Queue[bx]        ; 구한 인덱스릐 큐 값을 DL에 넣는다. -> DL
    mov Queue[bx], 0        ; 값을 빼고 빈자리에 'x'를 넣는다.

    inc Position            ; 인덱스를 다음 값의 위치로 셋팅
    dec QueueSize            ; 큐 사이즈를 하나 줄인다.


   

    pop cx                ;---------------------------------
    pop si                ; 레지스터 복원
    pop bx                ; cx, si, bx, ds, ax
    pop ds                ;
    pop ax                ;---------------------------------
               
    ret

    LABEL_BufferEmpty:
   
       
    ShowAllQueueDebugString

    mov QueueSize, 0
    mov TempPos, 0
    mov Position, 0

    NextLine



    pop cx                ;---------------------------------
    pop si                ; 레지스터 복원
    pop bx                ; cx, si, bx, ds, ax
    pop ds                ;
    pop ax                ;---------------------------------
               

    ret
    DeQueue ENDP   

;-----------------------------------------------------------
code    ends
;-----------------------------------------------------------

        end   main

Posted by houdinist