Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

RFpro.ru: Ассемблер? Это просто! Учимся программировать


Хостинг портала RFpro.ru:
Московский хостер
Профессиональный ХОСТИНГ на базе Linux x64 и Windows x64

РАССЫЛКИ ПОРТАЛА RFPRO.RU

Чемпионы рейтинга экспертов в этой рассылке

Boriss
Статус: Академик
Рейтинг: 2494
∙ повысить рейтинг »
_Ayl_
Статус: Профессионал
Рейтинг: 1867
∙ повысить рейтинг »
vladisslav
Статус: 6-й класс
Рейтинг: 1227
∙ повысить рейтинг »

/ КОМПЬЮТЕРЫ И ПО / Программирование / Assembler (Ассемблер)

Номер выпуска:1357
Дата выхода:11.06.2010, 16:00
Администратор рассылки:Лысков Игорь Витальевич, Модератор
Подписчиков / экспертов:237 / 62
Вопросов / ответов:1 / 1
IRC-канал по теме:#assembler

Вопрос № 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] - но я-то хочу именно байт занести. Если я заношу слово, то программа компилируется, но работает неверно. Каким тогда образом занести байт переменной в двубайтный регистр?
Заранее спасибо.

Отправлен: 06.06.2010, 15:31
Вопрос задал: Adsorores, Посетитель
Всего ответов: 1
Страница вопроса »


Отвечает Лысков Игорь Витальевич, Модератор :
Здравствуйте, 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 (Россия) | Еще номера »
  • Отправить WebMoney:

  • Оценить выпуск »
    Нам очень важно Ваше мнение об этом выпуске рассылки!

    Задать вопрос экспертам этой рассылки »

    Скажите "спасибо" эксперту, который помог Вам!

    Отправьте СМС-сообщение с тестом #thank НОМЕР_ОТВЕТА
    на короткий номер 1151 (Россия)

    Номер ответа и конкретный текст СМС указан внизу каждого ответа.

    Полный список номеров »

    * Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи. (полный список тарифов)
    ** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются.
    *** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании.


    © 2001-2010, Портал RFpro.ru, Россия
    Авторское право: ООО "Мастер-Эксперт Про"
    Автор: Калашников О.А. | Программирование: Гладенюк А.Г.
    Хостинг: Компания "Московский хостер"
    Версия системы: 2010.6.16 от 26.05.2010

    В избранное