Консультация № 178953
06.06.2010, 15:31
0.00 руб.
0 2 1
Уважаемые эксперты! Подскажите, как можно с помощью клавиатуры в нижеприведённой программе заставить нарисованный прямоугольник двигаться в каком-либо направлении, например, влево-вправо. Желательно, чтобы и скорость движения можно было бы менять нажатием клавиш.
Можно ли указатель на маску объекта сделать не так, как у меня? Мне пришлось сначала командой 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] - но я-то хочу именно байт занести. Если я заношу слово, то программа компилируется, но работает неверно. Каким тогда образом занести байт переменной в двубайтный регистр?
Заранее спасибо.


Приложение:
.model tiny
.386
.code
.startup ; точка входа

mov ax,0013h ;vga 320x200x256
int 10h
mov ax, 0a000h
mov es, ax ;es - сегмент видео
MainLoop:
call DrawMovingImage

mov ah,1
int 16h
jz MainLoop
mov ah, 0 ;проверяем на код клавиши
int 16h
cmp ah, 1 ;по Esc выходим
je Exit
jmp MainLoop

Exit:
mov ax, 0003h ;назад в текстовый режим
int 10h
mov ax, 4c00h
int 21h

DrawMovingImage proc
pushad
cld
; Вычислить адрес начальной точки для вывода маски
; Умножить длину строки на номер строки(Y)
mov AX,StringLength
mov DX,[ImageS]
mul DX
; Прибавить длину колонки (X)
add AX,[ImageC]
mov DI,AX ;результат - в индексный регистр
; Записать адрес маски в индексный регистр
mov si,300h
lea SI,[byte ptr Flm] ;указатель на маску объекта

; Вывести изображение
mov DX,ImageH ;высота маски
M0: ; Вывести очередную строку маски
xor cx,cx
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
popad
ret
DrawMovingImage 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 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,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 ;колонка
; Размеры маски изображения
ImageL equ 16 ;ширина маски
ImageH equ 16 ;высота маски
END

Обсуждение

давно
Посетитель
7438
7205
07.06.2010, 16:56
общий
это ответ
Здравствуйте, 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 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,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 ;колонка
; Размеры маски изображения
ImageL 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 можно не писать
5
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
09.06.2010, 04:49
общий
Спасибо за ответы и за программу!
"Загрузку в si делаем командой lea SI,[Flm]" Странно, я делал так (сейчас уже сомневаюсь), но не компилировалось, сейчас всё прекрасно компилируется.
"xor cx, cx
mov cl, byte ptr ImageL"
Я вместо cl ошибочно писал cx.:(
В программе при изменении движения слева направо или наоборот происходит задержка во времени для смены движения. Я думал, при выводе в видеостраницу будет быстрее.
Форма ответа