Изменить программу, чтобы символ "рожица" двигался в обратном направлении - 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
Объяснение кода листинга программы
Список элементов:
- org 256 - начало программы, загрузка сегмента данных
- mov ax,3 - установка текстового видеорежима 80x25
- les di,[videomem] - загрузка в es:di адреса видеопамяти 0B800h:0000
- push di - сохранение es:di в стеке
- pop ds - восстановление ds из стека
- mov ax,0702h - подготовка рожицы (серая рожица на чёрном фоне)
- mov cx,79 - установка счётчика тиков
- main: stosw - вывод рожицы
- mov ebx,[46Ch] - подготовка к ожиданию 55 мс (это один тик)
- inc ebx - увеличение счётчика тиков
- cmp ebx,[46Ch] - проверка, достиг ли счётчик 55
- ja @b - если счётчик достиг или превысил 55, то переход на строку 9
- mov byte[es:di-2],' ' - стирание рожицы
- mov byte[es:di+2],' ' - стирание рожицы
- loop main - повторение вывода рожицы до окончания счётчика тиков
- pushf - сохранение флагов в стеке
- pop ax - восстановление ax из стека
- std - установка обратного направления рожицы
- test ax,10000000000b - проверка, было ли обратное направление установлено
- jz start - если обратное направление уже было, то переход на начало программы
- ret - выход из программы
- videomem dd 0B8000000h - описание сегмента памяти для видеопамяти Код выполняет следующую задачу: он рисует рожицу, которая движется в обратном направлении.