Изменить программу, чтобы символ "рожица" двигался в обратном направлении - Assembler

Узнай цену своей работы

Формулировка задачи:

Помогите! Нужно изменить программу ниже,чтобы символ "рожица", как только достигнул конца экрана, двигался обратно, и достигнув другого конца экрана закончил программу
; Макроопределение задержки на заданное время
delay   macro minutes,seconds,hundr
        local secs,mins,hrs,check,quit
        push_regs <ax,bx,cx,dx>; сохранить регистры
        read_time           ; считать текущее время
        mov     ah,ch     ; скопировать часы в АН,
        mov     al,cl     ;  минуты -в АL,
        mov     bh,dh     ;  секунды -в BH,
        mov     bl,dl     ;  сотые доли -в BL
; получить время конца паузы, добавляя значения
; входных параметров к текущему времени
        ifnb <minutes>
             add al,minutes
        endif
        ifnb <seconds>
             add bh,seconds
        endif
        ifnb <hundr>
             add bl,hundr
        endif
; учесть возможные переносы
        cmp     bl,100
        jb      secs
        sub     bl,100
        inc     bh
secs:   cmp     bh,60
        jb      mins
        sub     bh,60
        inc     al
mins:   cmp     al,60
        jb      hrs
        sub     al,60
        inc     ah
hrs:    cmp     ah,24
        jne     check
        sub     ah,ah
; ждать наступления полученного времени считыванием
; текущего  времени и сравнением с полученным
check:  read_time
        cmp     cx,ax
        ja      quit
        jb      check
        cmp     dx,bx
        jb      check
quit:   pop_regs <dx,cx,bx,ax> ; восстановить
        endm                   ; значения регистров
 
; Макроопределение занесения регистров в стек
;в заданном порядке
push_regs macro reg_list
        irp     reg,<reg_list>
        push    reg
        endm
        endm
 
; Макроопределение восстановления регистров
; из стека в заданном порядке
pop_regs macro reg_list
        irp     reg,<reg_list>
        pop     reg
        endm
        endm
 
; Макроопределение получения в AL случайного числа
;в промежутке 0 - lim, где lim=4-127
rand    macro lim
        local   strip
        push_regs <cx,dx,ax>; сохранить значения
                            ; регистров
        mov     ax,0   ; считать показания таймера
        int     1ah
        mov     ax,dx; поместить младшую часть в АХ
        mov     cl,lim   ; поместить lim и CL
; удалить из делимого (АХ) достаточное число
; старших битов, чтобы гарантировать отсутствие
; переполнения
        mov     dh,3fh; поместить в DH маску
                      ; для операции AND
        cmp     cl,64
        jae     strip
        shr     dh,1  ; если lim<64, удалить 3 бита
        cmp     cl,32
        jae     strip
        shr     dh,1  ; если lim<32, удалить 4 бита
        cmp     cl,16
        jae     strip
        shr     dh,1  ; если lim<16, удалить 5 бит
        cmp     cl,0
        jae     strip
        shr     dh,1  ; если lim<8, удалить 6 бит
        shr     dh,1
strip:  and     ah,dh  ; удалить биты
        div     cl   ; разделить результат в АХ
                     ; на lim в  CL
        mov     al,ah; поместить остаток в АL
        pop     cx   ; восстановить значения
        mov     ah,ch; регистров
        pop_regs <dx,cx>
        endm
 
; Макроопределение чтения текущего времени 
;(CH - часы, CL - минуты, DH - секунды, DL – сотые
; доли секунды)
read_time macro
        push    ax
        mov     ah,2ch; выбрать режим чтения
                      ; времени
        int     21h   ; считать время
        pop     ax
        endm
 
; Начало программы
code    segment
        assume cs:code
start:  push_regs <ax,bx,cx,dx>  ; сохранить 
                              ;значения регистров
        mov     ah,15 ; загрузить в ВН номер
        int     10h   ; активной страницы экрана
        mov     al, 2
        mov     ah,0  ; задать текстовый 
        int     10h   ; черно-белый режим 80*25
        mov     cx,1 ; установить счетчик символов
        mov     dl,0  ; установить столбец 0
        rand    24 ; выбрать строку через генератор
        mov     dh,al ; случайных чисел
crsr:   mov     ah,2  ;установить позицию курсора
        int     10h
        mov     al,2  ; задать символ - "рожицу"
        mov     ah,10 ; вывести символ  на экран
        int     10h
        delay   ,   ,12 ; выдержать паузу
        sub     al,al   ; стереть "рожицу"
        mov     ah,10
        int     10h
        inc     dl      ; выбрать следующую позицию
        cmp     dl,80   ; в столбце и выйти, если
        je      ext     ;  он равен 80
        cmp     dh,0  ; проверить не установлены ли
        je      ext   ; граничные значения строки
        cmp     dh,24 ; и если да, то выйти
        je      ext
        rand    60  ; используя генератор случайных
        cmp     al,20 ;  чисел, выбрать направление
        jbe     zero   ;  движения "рожицы": вверх,
        cmp     al,40  ;  вниз, вперед
        jbe     one
        jmp     crsr
zero:   inc     dh     ; двигаться вниз
        jmp     crsr
one:    dec     dh     ; двигаться вверх
        jmp     crsr
ext:    pop_regs <dx,cx,bx,ax> ; восстановить 
                               ;регистры
        mov     ah,4ch           ; выйти в DOS
        int     21h
code    ends
        end     start

Решение задачи: «Изменить программу, чтобы символ "рожица" двигался в обратном направлении»

textual
Листинг программы
org 256
mov  ax,3
int  10h                         ;устанавливаем текстовый видеорежим 80x25
les  di,[videomem]               ;загружаем в es:di адрес видеопамяти 0B800h:0000
push di
pop  ds                          ;обнуляем ds - из этого сегмента будем считывать счётчик тиков
start:mov  ax,0702h              ;в ax серая рожица на чёрном фоне
      mov  cx,79
      main:stosw                 ;рисуем рожицу
           
           mov ebx,[46Ch]        ;ждём 55 мс - это один тик
           inc ebx               
           @@:cmp ebx,[46Ch]
           ja @b
 
           mov byte[es:di-2],' ' ;стираем рожицу
           mov byte[es:di+2],' '
      loop main
      pushf
      pop  ax
      std                        ;устанавливаем обратное направление рожицы
      test ax,10000000000b       ;если обратное направление уже было - выход из программы
jz start
ret
videomem dd 0B8000000h

Объяснение кода листинга программы

Список элементов:

  1. org 256 - начало программы, загрузка сегмента данных
  2. mov ax,3 - установка текстового видеорежима 80x25
  3. les di,[videomem] - загрузка в es:di адреса видеопамяти 0B800h:0000
  4. push di - сохранение es:di в стеке
  5. pop ds - восстановление ds из стека
  6. mov ax,0702h - подготовка рожицы (серая рожица на чёрном фоне)
  7. mov cx,79 - установка счётчика тиков
  8. main: stosw - вывод рожицы
  9. mov ebx,[46Ch] - подготовка к ожиданию 55 мс (это один тик)
  10. inc ebx - увеличение счётчика тиков
  11. cmp ebx,[46Ch] - проверка, достиг ли счётчик 55
  12. ja @b - если счётчик достиг или превысил 55, то переход на строку 9
  13. mov byte[es:di-2],' ' - стирание рожицы
  14. mov byte[es:di+2],' ' - стирание рожицы
  15. loop main - повторение вывода рожицы до окончания счётчика тиков
  16. pushf - сохранение флагов в стеке
  17. pop ax - восстановление ax из стека
  18. std - установка обратного направления рожицы
  19. test ax,10000000000b - проверка, было ли обратное направление установлено
  20. jz start - если обратное направление уже было, то переход на начало программы
  21. ret - выход из программы
  22. videomem dd 0B8000000h - описание сегмента памяти для видеопамяти Код выполняет следующую задачу: он рисует рожицу, которая движется в обратном направлении.

Оцени полезность:

12   голосов , оценка 4.333 из 5
Похожие ответы