code   SEGMENT 
       ASSUME cs:code, ds:mydata, es:mydata
main   proc  FAR    ;стандартное начало прогр.
       push  es
       mov   ax,0
       push  ax
;------------------------
       mov   ax,mydata  ; загрузка адреса сегментнов
       mov   ds,ax
       mov   es,ax
;------------------------ начало программы
;---очистка экрана путем установки нового режима
      MOV  AH,0      ;номер функции установки режима дисплея
      MOV  AL,2      ;код режима 80*25 черно-белого
      INT  10H       ;очистка экран
      mov  byte ptr x,10 ; начальное положение курсора
      mov  byte ptr y,10
      mov   byte ptr char,'*'  ; начальный символ
      call puts_char
NEXT:
; ---- Прием символа без ожидания
      MOV  AH,6           ;номер функции DOS
      MOV  DL,0FFH        ;запрос ввода с клавиатуры
      INT  21H            ;получение символа
      JZ   NEXT           ;переход если нет символа
      cmp  AL,27           ;если ввели ESC - закончить
      je   endd 
      CMP  AL,0           ;проверка на расширенный код
      JE   EXTENDED_CODE  ;если да, то на спец. процедуру
; ...                     ;иначе в AL код ASCII
      mov  char,AL        
     jmp  NEXT

;---процедура обработки расширенных кодов
;---анализ расширенных кодов (2-й байт кода в AL):
EXTENDED_CODE:
               INT   21H        ;---AL содержит символ управления курсором, анализируем его:
               CMP  AL,72       ;"курсор-вверх"?
               JE   C_U         ;если да, то на процедуру
               CMP  AL,80       ;"курсор-вниз"?
               JE   C_D         ;если да, то на процедуру
               CMP  AL,75       ; "курсор налево"  
               JE   C_L         ;если да, то на процедуру
               CMP  AL,77       ; "курсор направо"
               JE   C_R         ;если да, то на процедуру

               jmp  NEXT        ; другой код - пропустить
C_U:           CALL CURSOR_UP   ;вызов соответствующей процедуры
               JMP  NEXT        ;переход к следующему символу
C_D:           CALL CURSOR_DOWN ;вызов соответствующей процедуры
               JMP  NEXT        ;переход к следующему символу
C_L:           CALL CURSOR_LEFT ;вызов соответствующей процедуры
               JMP  NEXT        ;переход к следующему символу
C_R:           CALL CURSOR_RIGTH ;вызов соответствующей процедуры
               JMP  NEXT        ;переход к следующему символу
endd:
;-----------------------------------
       RET
main   endp
CURSOR_UP  proc             ; вверх         
           dec byte ptr y    ; уменьшить у
           mov AH,y          ; если вышли за границы экрана
           cmp AH,0          ; "вверх" экрана 
           JG  m_u
           mov AH,ymax        ; установить "низ экрана"
           mov y,AH  
m_u:
          call puts_char     ; нарисовать символ
          ret
CURSOR_UP  endp

CURSOR_DOWN  proc   ; вниз
             inc byte ptr y
             mov AH,y 
             cmp AH,ymax
             JLE   m_d
             mov byte ptr y,0  
m_d:
            call puts_char
            ret
CURSOR_DOWN  endp

CURSOR_LEFT  proc  ;  на лево
             dec   byte ptr x
             mov  ah,x
             cmp  AH,0
             JG   m_l
             mov   AH,xmax
             mov   x,AH
m_l:
             call puts_char 
             ret
CURSOR_LEFT  endp

CURSOR_RIGTH  proc  ; на право
             inc   byte ptr x
             mov  ah,x
             cmp  AH,xmax
             JLE   m_r
             mov  byte ptr x,0
m_r:
             call puts_char 
             ret
CURSOR_RIGTH  endp

curs_xy  proc
;---установка курсора в x, y экрана
         MOV  AH,2     ;функция установки курсора
         MOV  BH,0     ;номер страницы
         MOV  DH,y     ;координаты x,y
         MOV  DL,x 
         INT  10H      ;устанавливаем курсор
         ret 
curs_xy  endp

puts_char   proc  
            call curs_xy
            MOV  AH,2           ;функция вывода символа на экран
            MOV  DL,char         ;помещаем символ в DL перед выводом
            INT  21H            ;выводим его на экран
            ret 
puts_char  endp  

code   ends

mydata segment
x      db    0      ; положение курсора
y      db    0
xmax   db    79
ymax   db    24
char   db    '*'
mydata  ends
;----------------------------------
STK    SEGMENT STACK
        DW 64 DUP (?)
STK    ENDS
       END main
