Вопрос № 178953: Уважаемые эксперты! Подскажите, как можно с помощью клавиатуры в нижеприведённой программе заставить нарисованный прямоугольник двигаться в каком-либо направлении, например, влево-вправо. Желательно, чтобы и скорость движения можно было бы менять наж...
Вопрос № 178953:
Уважаемые эксперты! Подскажите, как можно с помощью клавиатуры в нижеприведённой программе заставить нарисованный прямоугольник двигаться в каком-либо направлении, например, влево-вправо. Желательно, чтобы и скорость движения можно было бы менять нажатием клавиш. Можно ли указатель на маску объекта сделать не так, как у меня? Мне пришлось сначала командой mov si,300h дать месторасположение маски, а только потом командой lea SI,[byte ptr Flm] указывать это месторасположение. А месторасположение давал наугад
с учётом примерной длины программы плюс запас. Когда я размеры маски изображения даю через константы ImageL equ 16 и ImageH equ 16, то программа с командами типа mov DX,ImageH и mov CX,ImageL компилируется без ошибок. А если через переменные ImageL db 16 и ImageH db 16, то появляется ошибка на соответствие операндов: Operand types do not match. Менял на mov CX,byte ptr ImageL, mov CX,byte ptr [ImageL], mov СX,byte ptr 1[ImageL], но правильно компилируется, только е
сли переопределять не байт, а слово: mov CX,word ptr [ImageL] - но я-то хочу именно байт занести. Если я заношу слово, то программа компилируется, но работает неверно. Каким тогда образом занести байт переменной в двубайтный регистр? Заранее спасибо.
Отвечает Лысков Игорь Витальевич, Модератор :
Здравствуйте, Adsorores. Сначала программа. Скорость меняется при нажатой клавише shift
Код:
.model tiny .386 .code .startup ; точка входа
mov ax,0013h ;vga 320x200x256 int 10h mov ax, 0a000h mov es, ax ;es - сегмент видео
cld MainLoop: call DrawMovingImage WaitKey: mov ah,1 int 16h jz MainLoop mov ah, 0 ;проверяем на код клавиши int 16h cmp ah, 1 ;по Esc выходим je Exit call GetStep ;по клавише Shift определим шаг 1 или 10 cmp ah, 4bh ;стрелка влево je left cmp ah, 4dh ;стрелка вправо jne WaitKey ;все остальное игнорируем right: mov ax, StringLength;проверим правый край sub ax, ImageL sub ax, bx ;ax - самая
правая позиция, при которой ; при добавлении шага не выйдем за правый край cmp ax, ImageC ;сравним с текущей jbe WaitKey call ClearImage ;ичищаем старое add ImageC, bx ;добавляем шаг jmp MainLoop ;и на прорисовку
left: mov ax, ImageC ;проверим, можем ли сдвинуться влево sub ax, bx jl WaitKey call ClearImage ;вытираем старое sub ImageC, bx ;уменьшаем шаг jmp MainLoop ;перерисовываем
Exit: mov ax, 0003h ;назад в текстовый режим int 10h mov ax,
4c00h int 21h
DrawMovingImage proc pusha ; Вычислить адрес начальной точки для вывода маски ; Умножить длину строки на номер строки(Y) mov AX,StringLength mov DX,[ImageS] mul DX ; Прибавить длину колонки (X) add AX,[ImageC] mov DI,AX ;результат - в индексный регистр ; Записать адрес мас
ки в индексный регистр lea SI,[Flm] ;указатель на маску объекта
; Вывести изображение mov DX,ImageH ;высота маски M0: ;Вывести очередную строку маски mov CX,ImageL ;ширина маски M1: ; Проверить точку маски lodsb and AL,AL ;код цвета равен нулю? jz M2 ;пропустить точку mov ES:[DI],AL ;вывести точку M2: ; Перейти к следующей точке inc DI loop M1
; Перейти на следующую строку add DI,StringLength sub DI,ImageL dec DX jnz M0 popa ret DrawMovingImage endp
ClearImage proc pusha ; Вычислить адрес начальной точки для вывода маски ; Умножить длину строки на номер строки(Y) mov AX,StringLength mov DX,[ImageS] mul DX
; Прибавить длину колонки (X) add AX,[ImageC] mov DI,AX ;результат - в индексный регистр ; Записать адрес маски в индексный регистр lea SI,[Flm] ;указатель на маску объекта
; Вывести изображение mov DX,ImageH ;высота маски M3: ;Вывести очередную строку маски mov CX,ImageL ;ширина маски mov al, 0 rep stosb ;cx раз прописываем 0 - вот и все вытирание :) ; Перейти на следующую строку add
DI,StringLength sub DI,ImageL dec DX jnz M3 popa ret ClearImage endp
;возвращаем в bx шаг для перемещений GetStep proc push ax mov ah, 2 ;читаем флаги клавиатуры int 16h mov bx, 1 ;шаг = 1, если нет нажатия на shift and al, 3 ;левый/правый jz GSRet mov bx, 10 ;шаг = 10, если есть нажатие на shift GSRet: pop ax ret GetStep endp
.data ;
Маска Flm DB 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15 DB 15,12,12,12,12,12,12,12,12,12,12,12,12,12,12,15 DB 1
5,12,12,12,12,12,12,12,12,12,12,12,12,12,12,15 DB 15,12,12,12,12,12,12,12,12,12,12,12,12,12,12,15 DB 15,12,12,12,12,12,12,12,12,12,12,12,12,12,12,15 DB 15,12,12,12,12,12,12,12,12,12,12,12,12,12,12,15 DB 15,12,12,12,12,12,12,12,12,12,12,12,12,12,12,15 DB 15,12,12,12,12,12,12,12,12,12,12,12,12,12,12,15 DB 15,12,12,12,12,12,12,12,12,12,12,12,12,12,12,15 DB 15,12,12,12,12,12,12,12,12,12,12,12,12,12,12,15 DB 15,12,12,12,12,12,12,12,12,12,12,12,12,12,12,15
DB 15,12,12,12,12,12,12,12,12,12,12,12,12,12,12,15 DB 15,12,12,12,12,12,12,12,12,12,12,12,12,12,12,15 DB 15,12,12,12,12,12,12,12,12,12,12,12,12,12,12,15 DB 15,12,12,12,12,12,12,12,12,12,12,12,12,12,12,15 DB 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15 StringLength dw 320 ;длина строки ; Позиция маски изображения на экране ImageS dw 100 ;строка ImageC dw 160 ;колонка ; Размеры маски изображения Ima
geL equ 16 ;ширина маски ImageH equ 16 ;высота маски END
Теперь вопросы: 1) Загрузку в si делаем командой lea SI,[Flm] 2) Загрузить байт в слово можно несколькими способами, например: а) обнулить весь регистр/старшую половину до xor cx, cx mov cl, byte ptr ImageL б) обнулить старшую часть после mov cl, bImageL xor ch, ch (and cx, 0ffh) в) воспользоваться командой 386 процессора movzx cx, byte ptr ImageL Если ImageL - байтовая переменная, то byte ptr
можно не писать
----- Удачи!
Ответ отправил: Лысков Игорь Витальевич, Модератор
Ответ отправлен: 07.06.2010, 16:56
Номер ответа: 261960 Украина, Кировоград Тел.: +380957525051 ICQ # 234137952 Mail.ru-агент: igorlyskov@mail.ru Абонент Skype: igorlyskov
Оценка ответа: 5
Вам помог ответ? Пожалуйста, поблагодарите эксперта за это! Как сказать этому эксперту "спасибо"?
Отправить SMS#thank 261960
на номер 1151 (Россия) |
Еще номера »
Оценить выпуск »
Нам очень важно Ваше мнение об этом выпуске рассылки!
* Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи.
(полный список тарифов)
** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются.
*** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании.