Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Управление квадратом по экрану

34K
28 января 2008 года
AsmBeginer
8 / / 28.01.2008
Здравствуйте. Вы немогли бы посмотреть исходник. Я написал программку, которая перемещает квадрат по экрану. Управление происходит клавишами со стрелкой. При нажатии на какую-либо из них, прога слетает. Почему, понять не могу. Я подозреваю, что надо сохранять регистры "push", а потом использовать "pop". Только не понимаю, на каких стади программы. Код не оптимизированн. Я хочу сначала написать рабочую версию, а потом оптимизировать. Иначе я не разберусь. Код простой. Сначала покажется что, 'темный лес', а через три-четыре секунды, Вы увидите что все отлично видно. У меня там просто повторение кусков кода.
================================================== ===
Логика программы:

1. Переменные с инициализацией.

2. Установка видеорежима

3. *Команда вывода точки в цикле (прорисовываю квадрат)

4. ловлю нажатие клавиши (key_loop) и переход в обработчик:

если ESC, quit
если вниз, key_down
если вверх, key_up
если влево, key_left
если вправо, key_right
если влево-вверх, key_home
если вправо-вверх, key_pgup
если влево-вниз, key_end
если враво-вниз, key_pgdn
(далее см. 6 пункт)

5. *Циклический вывод точки (прорисовываю квадрат по новым

координатам полученным из обработчика) и переход
в 4 пункт

6. В обработчике выводится черный квадрат поверх синего, для

закраски, изменяются переменные, прорисовывающие квадрат и

переход на 5 пункт.

*Пункт 3 для начального положения квадрата на экране.
*Пункт 5 для прорисовки квадрата по новым переменным.
================================================== ===
Посмотрите, пожалуйста, если Вам не трудно.
1.6K
28 января 2008 года
Vov4ick
476 / / 01.02.2007
Я бы никогда не додумался писать программы в ворде ;-)
34K
29 января 2008 года
AsmBeginer
8 / / 28.01.2008
Спасибо брат. Как сказать по другому, незнаю.
34K
31 января 2008 года
AsmBeginer
8 / / 28.01.2008
Я не разобрался в коде :(
решил сделать по минимуму, пока.
Отрезок. При начале работы вычерчивается отрезок. Нажимаю вврех или вниз, отрезок пропадает и прога виснет. Не реагирует на клавиши.
Код:
.model  tiny
    .code        
    org 100h

begin:  jmp setup

number1 dw 100
number2 dw 100
number9 dw 100
number10 dw 100
count1 dw 200
count5 dw 200
;=============
setup:
       mov AX,11h
       int 10h
back:
       MOV AH,0CH
       MOV AL,3
;====================GV
       mov  CX, number1     ;начальная коордната Х
       mov  DX, number2     ;начальная коордната Y
label_1:
       inc  cx         ; Х=Х+1
       int  10h        ; вывести пиксель

       cmp  cx, count1    ; цикл 200 раз
jle  label_1            ; goto label_1

key_loop:

    mov ah,7         ;ждем символ с клавы
    int 21h

    cmp  al,27      ; нажали Esc?
    je   quit          ; да, выход
    test al,al         ;провнрка на 0 начало
    jnz key_loop   ;если да не выходим, ждем другую клавишу
    int 21h

    cmp al,50h      ;сравнение со стрелкой вниз
    je key_down    ;переход в обработчик

    cmp al,48h      ;сравнение со стрелкой вверх
    je key_up        ;переход в обработчик

       MOV AH,0CH
       MOV AL,0
;==================================================
black proc                        ; закрас
       mov  CX, number9      ;начальная коордната Х
       mov  DX, number10     ;начальная коордната Y
   label_5:
       inc  cx                      ; Х=Х+1
       int  10h                     ; вывести пиксель

       cmp  cx, count5    ; цикл 200 раз
   jle  label_5            ; goto label_1
black endp
;==================================================
key_up:
        call black
        dec  number2     ;строка
        dec number10     ;строка
        jmp back
key_down:
        call black
        inc  number2     ;строка
        inc number10     ;строка
        jmp back
quit:
        mov ax,0003h    ; востановить текстовый режим
    int 10h
 RET
end begin

Похоже действительно нужно что-то сохранять, где ошибка, не могу найти. Может очистку экрана делать, перед рисованием отрезка?
1.6K
31 января 2008 года
Vov4ick
476 / / 01.02.2007
Ты забыл сделать возврат из процедуры.
В моей роге всё просто. Читай названия меток и комментарии.
34K
31 января 2008 года
AsmBeginer
8 / / 28.01.2008
Цитата:
Ты забыл сделать возврат из процедуры.


В вызове call black?
так там не надо. это же вызов подпрограммы. после её работы, сохраненный адрес следущей строки берется из стека и работа идет с этого адреса.

В обработчике клавиши key_up/key_down?
я поставил jmp back.

Цитата:
В моей роге всё просто. Читай названия меток и комментарии


я не разобрался. там множественные goto и множественные сохранения в стеке :(

1.6K
31 января 2008 года
Vov4ick
476 / / 01.02.2007
Цитата:
так там не надо. это же вызов подпрограммы. после её работы, сохраненный адрес следущей строки берется из стека и работа идет с этого адреса.


Прямо сам и берётся? Процессоры пока не научились читать мысли программиста и требуют для работы прямых команд. Для выборки из стека адреса и перехода по нему используется команда RET (RETN, RETF).

Цитата:
там множественные goto


А я думал, что на асемблере писал... ;-)
Откомментировал исходник получше. Если что непонятно, задавай конкретные вопросы, а не "множественные гото", можно в аську, чтобы форум не засорять.

Код:
max_x   = 1023                   ;
max_y   = 767                    ; Размер экрана в используемом видеорежиме
;         RRRRRGGGGGGBBBBB
color   = 0100011111111111b      ; Цвет прямоугольника
start_x = max_x/2                ; \
start_y = max_y/2                ; -- Начальные координаты прямоугольника
sx      = 30                     ; \
sy      = 50                     ; -- Удвоенные размеры прямоугольника

ideal
model tiny
codeseg
p386
org 100h
start:
                mov     ax,4f02h        ; Установка режима
                mov     bx,117h         ; 1024x768 2 байта на точку
                int     10h

                cmp     ax,4fh          ; Функция поддерживается?
                jne     error

                mov     ax,0a000h       ; Сегментный адрес окна видеопамяти
                mov     es,ax
;-------------- ------- ------------------------
                dec     sp
                dec     sp
redraw:
                inc     sp
                inc     sp
              ; Здесь выведем линейку по краю экрана
                mov     ax,0f000h       ; Цвет
                xor     bx,bx           ; X=0
                xor     dx,dx           ; Y=0
ruler:
                mov     cx,dx
line:
                call    pixel
                inc     bx
                call    pixel
                inc     bx

                cmp     bx,32
                je      step

                shr     cx,1
                jnc     line
step:
                xor     bx,bx
                inc     dx
                cmp     dx,max_y
                jne     ruler
;-------------- ------- ------------------------
                mov     dx,start_y   ; Начальные
                mov     bx,start_x   ;           координаты
                mov     ax,color     ;     и цвет
keyscan:
                push    ax

                mov     ah,0            ; Ждём нажатия
                int     16h             ; клавиши
;---------------------------
                cmp     ah,48h          ; Стрелка вверх
                je      up_arrow
                cmp     ah,50h          ; Стрелка вниз
                je      down_arrow
                cmp     ah,4bh          ; Стрелка влево
                je      left_arrow
                cmp     ah,4dh          ; Стрелка вправо
                je      right_arrow
                cmp     ah,47h          ; HOME
                je      home
                cmp     ah,49h          ; PgUp
                je      PgUp
                cmp     ah,4fh          ; End
                je      EndA
                cmp     ah,51h          ; PgDn
                je      PgDn
                cmp     ah,1            ; ESC
                je      exit
                cmp     ah,1ch          ; Ввод
                je      redraw

                pop     ax
                jmp     keyscan
up_arrow:
                pop     ax              ; Цвет
                cmp     dx,sy           ; Край экрана
                je      keyscan         ; Край экрана - сначала
                call    clear           ; Чёрный квадрат
                dec     dx              ; Переместить вверх
                call    square          ; Цветной квадрат
                jmp     keyscan         ; Сначала
down_arrow:
                pop     ax
                cmp     dx,max_y-sy
                je      keyscan
                call    clear
                inc     dx
                call    square
                jmp     keyscan
left_arrow:
                pop     ax
                cmp     bx,sx
                je      keyscan
                call    clear
                dec     bx
                call    square
                jmp     keyscan
right_arrow:
                pop     ax
                cmp     bx,max_x-sx
                je      keyscan
                call    clear
                inc     bx
                call    square
                jmp     keyscan
home:
                pop     ax
                cmp     bx,sx
                jz      keyscan
                cmp     dx,sy
                jz      keyscan
                call    clear
                dec     dx
                dec     bx
                call    square
                jmp     keyscan
PgUp:
                pop     ax
                cmp     bx,max_x-sx
                je      keyscan
                cmp     dx,sy
                jz      keyscan
                call    clear
                dec     dx
                inc     bx
                call    square
                jmp     keyscan
EndA:
                pop     ax
                cmp     bx,sx
                je      keyscan
                cmp     dx,max_y-sy
                je      keyscan
                call    clear
                inc     dx
                dec     bx
                call    square
                jmp     keyscan
PgDn:
                pop     ax
                cmp     bx,max_x-sx
                je      keyscan
                cmp     dx,max_y-sy
                je      keyscan
                call    clear
                inc     bx
                inc     dx
                call    square
                jmp     keyscan
exit:
                pop     ax
error:
                mov     ax,3            ; Текстовый режим
                int     10h
                ret                     ; Выход
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
proc clear near   ; Рисует чёрный квадрат
  ; BX=x ; DX=y ; ES=VideoRAMsegm
                push    ax
                xor     ax,ax           ; Чёрный цвет
                call    square          ; Нарисовать
                pop     ax
                ret
endp clear
;-------------- ------- ------------------------
proc square near
  ; AX=colour BX=x ; DX=y ; ES=VideoRAMsegm
                push    bx dx

                mov     si,bx
                mov     di,dx

                add     si,sx+1         ;
                add     di,sy+1         ; Конец квадрата

                sub     bx,sx           ;\
                sub     dx,sy           ; > Начало квадрата
                mov     cx,bx           ;/

                or      ax,ax           ; Закраска чёрным?
                jnz     row
                call    waitvsync       ; Да - Ждать обратного хода луча
row:
                call    pixel
                inc     bx              ; X+1
                cmp     bx,si
                jne     row             ; Вывод строчки прямоугольника

                mov     bx,cx           ; X=X0
                inc     dx              ; Y+1   - след. строка
                cmp     dx,di
                jne     row

                pop     dx bx
                ret
endp square
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
proc pixel near   ; Вывод точки
  ; AX=colour(ch=0?) ; BX=x ; DX=y ; ES=VideoRAMsegm
                push    ax bx dx
                push    ax              ; Цвет
                push    bx              ; x
                push    dx              ; y
                                        ; 1024*2 => 32 строки в окне
                shr     dx,5            ; dx/32
                cmp     dx,[bank]       ; Текущее окно видеопамяти
                je      win_ok
                mov     [bank],dx

                mov     ax,4f05h        ; Сделать текущим окно в DX
                xor     bx,bx
                int     10h
win_ok:
                pop     ax              ; Y
                and     ax,11111b       ; y%32 - координата в окне
                shl     ax,11           ; Y*2048

                pop     bx              ; X
                shl     bx,1            ; X*2 бита на точку
                add     bx,ax           ; коорд. в окне

                pop     ax              ; цвет
                mov     [es:bx],ax      ; Записать точку
                pop     dx bx ax
                ret
bank dw 0
endp pixel
;-------------- ------- ------------------------
proc waitvsync near  ; Ожидание обратного хода луча
                push    ax
                push    dx
                mov     dx,03dah ;регистр статуса VGA
@@wait1:
                in      al,dx
                and     al,08h ;выделяем бит вертикальной синхронизации
                jnz     @@wait1
@@wait2:
                in      al,dx
                and     al,08h ;выделяем бит вертикальной синхронизации
                jz      @@wait2
                pop     dx
                pop     ax
                ret
endp waitvsync

end start
34K
31 января 2008 года
AsmBeginer
8 / / 28.01.2008
я поставил ret в конец обработчика

black proc

ret
black endp

все рано не получается, ну как сделать... то..?
:(
1.6K
31 января 2008 года
Vov4ick
476 / / 01.02.2007
Заметил ещё одну ошибку. Что произойдёт, если нажать кнопку, отличную от ОТМЕНА, ВВЕРХ или ВНИЗ ? Программа пойдёт выполняться дальше - по процедурам. Потому и виснет.
Ещё один совет. Давай переменным более осмысленные названия, чем number1, number2 и т.п., иначе на следующий день будешь долго разбираться в своей же программе, да и в процессе написания будут сложности с пониманием того, что где лежит.
34K
31 января 2008 года
AsmBeginer
8 / / 28.01.2008
у меня получилось, все дело в je, jz, jmp.
чтоб работало, нужно ставить jz, правда прога слетает, если нажать что-то кроме ESC, up, down.
Почему слетает? Потому что не выходит из графического режима перед выходом.
1.6K
31 января 2008 года
Vov4ick
476 / / 01.02.2007
je - это та же самая команда, что и jz.
34K
31 января 2008 года
AsmBeginer
8 / / 28.01.2008
я в WinAsm 2.0 пишу. Может по этому?
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог