Вопрос № 179122: В приложении программа движущегося вертикально вниз отрезка. Помогите сделать, чтобы так же выводилась и двигалась маска размером, например, 3х5 байт. Msk db 01,04,01 01,04,01 01,04,01 01,04,01Вопрос № 179128: Здравствуйте уважаемые эксперты! Помогите пожалуйста решить следующую задачу: Написать рекурсивную процедуру решения задачи о "Ханойской башне". Прошу подробные комментарии, т.к. в ассемблере не очень. Программа Tasm 5.0. Буду...
Вопрос № 179122:
В приложении программа движущегося вертикально вниз отрезка. Помогите сделать, чтобы так же выводилась и двигалась маска размером, например, 3х5 байт. Msk db 01,04,01 01,04,01 01,04,01 01,04,01 01,04,01 В режиме 13h я смог сделать движение маски, а в 12h не могу даже вывести на экран маску – у меня просто регистров почему-то не хватает.
mov ax, 0012h ;графический режим 12h, vga 640х480х16 int 10h
mov dx, 03CEh ;индексный порт
графического контроллера mov ax, 0F01h ;регистр 01h: разрешение установки/сброса out dx, ax
mov ax, 0a000h mov es, ax ; es - сегмент видео MainLoop: call Draw,offset msk ;адрес маски call DELAY ;задержка
mov ah,1 ;проверка на нажатие клавиши int 16h jz @@1 cmp al,' ' ; пробел - пауза, можно рассмотреть рисунок jne @@1 mov ah, 0 ;извлекаем код клавиши из буфера int 16h xor ax,ax
; ждем нажатия клавиши int 16h cmp ah, 1 ; по Esc выходим je Exit @@1: call Draw,offset black ;стираем add row,5 ;шаг движения call Proverka ;проверка на последнюю строку
mov ah,1 ;проверка на нажатие клавиши int 16h jz MainLoop mov ah, 0 ;извлекаем код клавиши из буфера int 16h cmp ax,4b00h ; влево jne @@2 dec [column] jmp MainLoop @@2: cmp ax,4d00h ; вправо jne @@3 inc [column] jmp MainLoop @@3: cmp ah, 1 ;по
Esc выходим jne MainLoop Exit: mov ax, 0003h ;восстановим текстовый режим int 10h
.286 Draw proc maska: word ; вычислить номер байта в видеопамяти mov ax, [row] ;AX = строка mov bx, 80 mul bx ;AХ = АХ * 80 = строка * байт_в_строке
mov di, ax ;сохранить адрес начала строки в di mov ax, [column] mov cl, al shr ax,
3 ;AX = номер байта в строке add di, ax ;DI = номер байта в видеопамяти and cl, 7 ;вычислить номер бита в байте, остаток от ; деления на 8 – номер бита в байте mov ch, 80h shr ch, cl ;нужный бит установлен в 1 mov dx, 03CEh ;индексный порт графического контроллера
mov si,[maska] mov bl,[si] ; число строк inc si mov cl,[si] ; число столбцов inc si @@next_row: push di ; сохраняем смещение начала маски в видеобуфере push cx ; маска пикселя
и число столбцов
@@next_pixel: mov ah, [si] ;цвет mov al, 0 ;al = регистр установки/сброса out dx, ax ;ah = цвет
mov al, 8 ; al = битовая маска mov ah, ch ;записать в битовую маску нули всюду, кроме out dx, ax ;бита, соответствующего выводимому пикселю
xchg es:[di],ah ;заполнить регистры-защелки и вывести на экран пиксель
inc si ; к следующему байту маски ror ch,1 ; маска для следующего пикселя jnc @@
2 inc di ; к следующему байту видеобуфера @@2: dec cl jnz @@next_pixel pop cx ; восстанавливаем маску pop di add di,80 ; к следующей строке dec bl jnz @@next_row ret Draw endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; time equ 30 ;число интервалов по 10мс DELAY: ; pusha ;сохраним все регистры mov ah,2dh ;сбросим время xor cx,cx xor dx,dx int 21h
dl2: mov ah,2ch ; читаем
время, GET SYSTEM TIME int 21h ; Return: CH = hour, CL = minute, DH = second, DL = 1/100 seconds ;считаем сотни мс mov al,100 mul dh ;секунды умножаем на 100 - ax = количество интервалов по 10мс xor dh,dh ;dx - число сотых xchg ax,dx ;поменяем местами mov cl,10 div cl ;ax = количество интервалов по 10мс из сотых add ax,dx ;складываем с количеством из секунд cmp ax,time ;сравним
с ожидаемым интервалом jl dl2 ;ждем, если меньше ; popa ;восстановим все регистры ret
;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Proverka proc cmp row,470 ;доходим почти до края экрана, обнуляем строку. Если сравнить с 479, то ;верхний следующий пунктир выведется не с 320 колонки, а больше. jb @@1 mov row,0 @@1: cmp [column],630 jb @@2 mov [column],1 @@2: cmp [column],0 ja @@3 mov [column],629 @@3: ret Proverka endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.data
column dw 320 row dw 0 Msk db 10,
7 ; размер маски в точках: строк, столбцов db 8,8,8,8,8,8,8 db 8,1,1,14,1,1,8 db 8,1,1,14,1,1,8 db 8,1,1,14,1,1,8 db 8,1,1,14,1,1,8 db 8,1,1,14,1,1,8 db 8,14,14,14,14,14,8 db 8,1,14,14,14,1,8 db 8,1,1,14,1,1,8 db 8,8,8,8,8,8,8
black db 10, 7 ; размер маски в точках: строк, столбцов db 0,0,0,0,0,0,0 db 0,0,0,0,0,0,0 db 0,0,0,0,0,0,0 db 0,0,0,0,0,0,0 db 0,0,0,0,0,0,0 db 0,0,0,0,0,0,0 db 0,0,0,0,0,0,
0 db 0,0,0,0,0,0,0 db 0,0,0,0,0,0,0 db 0,0,0,0,0,0,0 END
Дополнительно, я добавил возможность смещения выводимого шаблона вправо-влево по нажатию соответствующих стрелок (для проверки корректности функции отрисовки при переходе через границу байта) и паузу по пробелу (чтобы можно было спокойно рассмотреть рисунок на экране). В процедуре Draw вычисления вынесены за пределы цикла.
Ваша программа построена таким образом, что сохранение/восстановление регистров в процедурах
не требуется, поэтому я удалил или закомментировал pusha/popa.
Успехов!
Ответ отправил: amnick, Профессионал
Ответ отправлен: 16.06.2010, 15:54
Номер ответа: 262145
Оценка ответа: 5
Вам помог ответ? Пожалуйста, поблагодарите эксперта за это! Как сказать этому эксперту "спасибо"?
Отправить SMS#thank 262145
на номер 1151 (Россия) |
Еще номера »
Отвечает amnick, Профессионал :
Здравствуйте, Петров Юрий Иванович.
Теорию можно почитать, например, здесь. Решение на ассемблере:
Код:
.model tiny, pascal
N_RINGS =
4 ; число колец (до 9, иначе нужно менять вывод сообщения)
.data szInfo db 'Задача о "Ханойской башне" для ' db N_RINGS+'0',' колец.',13,10,'$' szMove db "0 -> 0",13,10,'$' szExit db "Press any key to exit...$"
.code .startup .286
; вывод информационного сообщения mov ah,9 ; AH=9 - вывод строки на экран mov dx,offset szInfo ; DS:DX = адр
ес выводимой строки int 21h
mov ah,9 ; AH=9 - вывод строки на экран mov dx,offset szExit ; DS:DX = адрес выводимой строки int 21h
xor ax,ax ; ждем нажатия клавиши int 16h
int 20h ; завершение программы (только .COM)
;--------------------------------------------------- ; AL = число колец ; from - начальное положение колец (1-3), ; to - конечное положение колец (1-3) ; temp -
промежуточный колышек (1-3) ;--------------------------------------------------- hanoi_towers proc from: word, to: word, temp: word test al,al ; число колец = 0? jz @@ret
dec ax ; вызываем для числа колец на 1 меньше push ax ; сохраняем для второго вызова call hanoi_towers, from, temp, to
; формируем сообщение mov al,byte ptr [from] add al,'0' ; номер колышка - в символ mov [szMove],al mov al,byte ptr [to
] add al,'0' ; номер колышка - в символ mov [szMove+5],al mov ah,9 ; вывод строки на экран mov dx,offset szMove ; DS:DX = адрес выводимой строки int 21h
pop ax ; восстанавливаем число колец call hanoi_towers, temp, to, from @@ret: ret hanoi_towers endp
end
Успехов!
Ответ отправил: amnick, Профессионал
Ответ отправлен: 16.06.2010, 18:38
Номер ответа: 262147
Оценка ответа: 5 Комментарий к оценке: Прога работает, спасибо)
Вам помог ответ? Пожалуйста, поблагодарите эксперта за это! Как сказать этому эксперту "спасибо"?
Отправить SMS#thank 262147
на номер 1151 (Россия) |
Еще номера »
Оценить выпуск »
Нам очень важно Ваше мнение об этом выпуске рассылки!
* Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи.
(полный список тарифов)
** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются.
*** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании.