IPB
ЛогинПароль:

> ПРАВИЛА РАЗДЕЛА!!!

1. Заголовок или название темы должно быть информативным
2. Все тексты программ должны помещаться в теги [CODE=asm] [/CODE]
3. Прежде чем задавать вопрос, см. "FAQ",если там не нашли ответа, воспользуйтесь ПОИСКОМ, возможно, такую задачу уже решали!
4. Не предлагайте свои решения на других языках, кроме Ассемблера. Исключение только с согласия модератора.
5. НЕ используйте форум для личного общения! Все, что не относиться к обсуждению темы - на PM!
6. Проверяйте программы перед тем, как выложить их на форум!!

 
 Ответить  Открыть новую тему 
> Построение и управление квадратиками
сообщение
Сообщение #1


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

Репутация: -  2  +


Имеется набор из 9-ти квадратиков. Выбор активного из них осуществляется нажатием соответствующей цифровой клавиши. Активный квадратик можно передвигать по полю, используя курсорные клавиши, а по нажатию "пробела" - менять его цвет. Написать программу построение различных фигур, испльзуя такой принцип управления.

Пока останавилась на построении набора квадратиков..Вот что получилось:

text segment 'code' ; (1) начало сегмента команд
assume CS:text,DS:data; (2)
vertical proc; (3) объявление процедуры построения вертикальной линии
v: ; (4)
push CX; (5) сохраним в стек счетчик цикла
mov AH,0Ch; (6) функция вывода пикселя
mov AL,6; (7) установка цвета
mov BH,0; (8) видеостраница
mov CX,SI; (9) установка X-координаты
int 10h; (10) вызов BIOS
inc DX; (11) счетчик Y-координаты
pop CX; (12) выгрузим из стека счетчик цикла
loop v; (13) уменьшим его на единицу
ret; (14) выход из подпрограммы
vertical endp; (15) конец текста подпрограммы
horizontal proc; (16) объявление процедуры построения горизонтальной линии
h: ; (17)
push CX; (18) сохраним в стек счетчик цикла
mov AH,0Ch; (19) функция вывода пикселя
mov AL,6; (20) установка цвета
mov BH,0; (21) видеостраница
mov CX,SI; (22) установка X-координаты
int 10h; (23) вызов BIOS
inc SI; (24) счетчик Х-координаты
pop CX; (25) выгрузим из стека счетчик цикла
loop h; (26) уменьшим его на единицу
ret; (27) выход из подпрограммы
horizontal endp; (28) конец текста подпрограммы

begin: ;(29) начало основной программы
mov AX,00h; (30) функция задания режима
mov AL,10h; (31) графический режим EGA
int 10h; (32) вызов BIOS
mov cx,3
rect: push cx
mov SI,100; (33) Х-координата
add si,i
mov DX,100; (34) Y-координата
add dx,i
mov CX,20; (35) длина стороны
call vertical; (36) вызов подпрограммы
mov SI,100; (37) Х-координата
add si,i
mov DX,100; (38) Y-координата
add dx,i
mov CX,20; (39) длина стороны
call horizontal; (40) вызов подпрограммы

mov SI,120; (33) Х-координата
add si,i
mov DX,100; (34) Y-координата
add dx,i
mov CX,20; (35) длина стороны
call vertical; (36) вызов подпрограммы

mov SI,100; (37) Х-координата
add si,i
mov DX,120; (38) Y-координата
add dx,i
mov CX,21; (39) длина стороны
call horizontal; (40) вызов подпрограммы
add i,22
pop cx
loop rect

mov AH,08h
int 21h

mov AH,00h
mov AL,03h
int 10h

mov AX,4C00h; (41) завершение программы
int 21h; (42)
text ends; (43) конец сегмента команд

data segment
i dw 0
data ends

stk segment stack
dw 128 dup (0)
stk ends

end begin; (44) конец текста программы




Хотела получить рядом расположенные квадратики..но как я предполагаю содержимое регистра СХ сбивается..
Как исправить - не пойму..

Сообщение отредактировано: 18192123 -


Эскизы прикрепленных изображений
Прикрепленное изображение
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


N337
****

Группа: Пользователи
Сообщений: 737
Пол: Мужской

Репутация: -  26  +


У тебя в начале программы не инициализируется DS и i хранится черт знает где (в PSP). Добавь его инициализацию:
begin:
mov ax,data
mov ds,ax


Сообщение отредактировано: xds -


--------------------
The idiots are winning.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

Репутация: -  2  +


Добавила перерисовку квадратов по нажатию соответствующей цифровой клавиши (пока только 1-го и 2-го из них) - т.е так мы активируем квадрат для последующего управления. Но не получается стирать ранее нарисованные - не могу "поймать" ту же позицию, чтоб перерисовать чёрным цветом..Та же проблема и с изменением цвета ранее нарисованного квадрата (переход на метку color)..

И самое непонятное - не могу организовать управление квадратами, чтоб получить фигурки..не пойму ,как это сделать наиболее рационально...Подкиньте пожалуста идеи..Объясните, как поступить..


text segment 'code' ; (1) начало сегмента команд
assume CS:text,DS:data; (2)
vertical proc; (3) объявление процедуры построения вертикальной линии
v: ; (4)
push CX; (5) сохраним в стек счетчик цикла
mov AH,0Ch; (6) функция вывода пикселя
;mov AL,15; (7) установка цвета
mov BH,0; (8) видеостраница
mov CX,SI; (9) установка X-координаты
int 10h; (10) вызов BIOS
inc DX; (11) счетчик Y-координаты
pop CX; (12) выгрузим из стека счетчик цикла
loop v; (13) уменьшим его на единицу
ret; (14) выход из подпрограммы
vertical endp; (15) конец текста подпрограммы
horizontal proc; (16) объявление процедуры построения горизонтальной линии
h: ; (17)
push CX; (18) сохраним в стек счетчик цикла
mov AH,0Ch; (19) функция вывода пикселя
;mov AL,15; (20) установка цвета
mov BH,0; (21) видеостраница
mov CX,SI; (22) установка X-координаты
int 10h; (23) вызов BIOS
inc SI; (24) счетчик Х-координаты
pop CX; (25) выгрузим из стека счетчик цикла
loop h; (26) уменьшим его на единицу
ret; (27) выход из подпрограммы
horizontal endp; (28) конец текста подпрограммы

rectangle proc
push cx
mov SI,10; (33) Х-координата
add SI,j
mov DX,10; (34) Y-координата
add dx,i
mov CX,20; (35) длина стороны
call vertical; (36) вызов подпрограммы
mov SI,10; (37) Х-координата
add SI,j
mov DX,10; (38) Y-координата
add dx,i
mov CX,20; (39) длина стороны
call horizontal; (40) вызов подпрограммы

mov SI,30; (33) Х-координата
add SI,j
mov DX,10; (34) Y-координата
add dx,i
mov CX,20; (35) длина стороны
call vertical; (36) вызов подпрограммы

mov SI,10; (37) Х-координата
add SI,j
mov DX,30; (38) Y-координата
add dx,i
mov CX,21; (39) длина стороны
call horizontal; (40) вызов подпрограммы
add i,30
pop cx
ret
rectangle endp

begin: ;(29) начало основной программы
mov ax,data
mov ds,ax

mov AX,00h; (30) функция задания режима
mov AL,10h; (31) графический режим EGA
int 10h; (32) вызов BIOS
mov cx,9

rect:
mov AL,15
call rectangle
loop rect

cikl:
mov AH,08h
int 21h
cmp AL,31h
je one
cmp AL,32h
je two
cmp AL,32
je color
cmp AL,44h
je exit
jmp cikl
one:
mov i,0
add j,30
mov AL,15
call rectangle
jmp cikl
two:
mov i,30
add j,30
mov AL,15
call rectangle
jmp cikl
color:
mov AL,12
call rectangle
jmp cikl
exit:
mov AH,00h
mov AL,03h
int 10h

mov AX,4C00h; (41) завершение программы
int 21h; (42)

text ends; (43) конец сегмента команд

data segment
i dw 0
j dw 0
data ends

stk segment stack
dw 128 dup (0)
stk ends

end begin; (44) конец текста программы


 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


N337
****

Группа: Пользователи
Сообщений: 737
Пол: Мужской

Репутация: -  26  +


Я бы использовал видеорежим с линейным буфером и вывод прямой записью в видеопамять. Тогда стирание старого изображения квадрата можно реализовать с помощью операции "исключающее ИЛИ", что упростит вывод нескольких квадратов с их перемещением. Примерно вот так:
BOX_SIZE	equ 20		;длина стороны квадрата
SCR_WIDTH equ 320 ;ширина экрана

locals

.model small

.stack 2048

.data

;координаты и цвет квадрата
x dw 10
y dw 20
color db 1

.code

;----- вывод квадрата с заданными координатами и цветом -----
draw_box:
;вичисление смещения в видеобуфере по заданным координатам x и y
;bx = y * SCR_WIDTH + x
mov ax,SCR_WIDTH
mul y
add ax,x
mov bx,ax
mov al,color
;вывод верхней стороны
mov cx,BOX_SIZE-1
@@1:
xor es:[bx],al
inc bx
loop @@1
;вывод правой стороны
mov cx,BOX_SIZE-1
@@2:
xor es:[bx],al
add bx,SCR_WIDTH
loop @@2
;вывод нижней стороны
mov cx,BOX_SIZE-1
@@3:
xor es:[bx],al
dec bx
loop @@3
;вывод левой стороны
mov cx,BOX_SIZE-1
@@4:
xor es:[bx],al
sub bx,SCR_WIDTH
loop @@4
ret

;----- основная программа -----
entry:
;инициализация ds
mov ax,@data
mov ds,ax

;запомнить в стеке номер текущего видеорежима
mov ah,0Fh
int 10h
push ax
;установка видеорежима 320x200x256
mov ax,13h
int 10h

;es:0 -> видеобуфер
mov ax,0A000h
mov es,ax

;вывод неподвижного квадрата
call draw_box

;начальные координаты и цвет перемещаемого квадрата
mov x,0
mov y,0
mov color,2

redraw:
;вывести квадрат
call draw_box

;ожидать нажатия клавиши
xor ax,ax
int 16h
;выход по ESC
cmp al,27
je exit

;стереть квадрат
call draw_box

;вычислить новые координаты
add x,2
inc y

jmp redraw

exit:
;восстановить видеорежим
pop ax
xor ah,ah
int 10h

;выход
mov ax,4C00h
int 21h

end entry


Сообщение отредактировано: xds -


--------------------
The idiots are winning.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

Репутация: -  2  +


Цитата(xds @ 19.04.2008 17:05) *

Я бы использовал видеорежим с линейным буфером и вывод прямой записью в видеопамять. Тогда стирание старого изображения квадрата можно реализовать с помощью операции "исключающее ИЛИ", что упростит вывод нескольких квадратов с их перемещением.


Спасибо большое..Так намного эффективнее..
У меня возникли ещё вопросы...
А как сделать, чтоб можно двигать несколько квадратов: подвинули один..потом второй..и так сколько нужно..?
Я попыталась - неудачно..

BOX_SIZE equ 20 ;длина стороны квадрата
SCR_WIDTH equ 320 ;ширина экрана

locals

.model small

.stack 2048

.data

;координаты и цвет квадрата
x dw 0
y dw 0
color db 1

.code

;----- вывод квадрата с заданными координатами и цветом -----
draw_box:
;вичисление смещения в видеобуфере по заданным координатам x и y
;bx = y * SCR_WIDTH + x
mov ax,SCR_WIDTH
mul y
add ax,x
mov bx,ax
mov al,color
;вывод верхней стороны
mov cx,BOX_SIZE-1
@@1:
xor es:[bx],al
inc bx
loop @@1
;вывод правой стороны
mov cx,BOX_SIZE-1
@@2:
xor es:[bx],al
add bx,SCR_WIDTH
loop @@2
;вывод нижней стороны
mov cx,BOX_SIZE-1
@@3:
xor es:[bx],al
dec bx
loop @@3
;вывод левой стороны
mov cx,BOX_SIZE-1
@@4:
xor es:[bx],al
sub bx,SCR_WIDTH
loop @@4
ret

;----- основная программа -----
entry:
;инициализация ds
mov ax,@data
mov ds,ax

;запомнить в стеке номер текущего видеорежима
mov ah,0Fh
int 10h
push ax
;установка видеорежима 320x200x256
mov ax,13h
int 10h

;es:0 -> видеобуфер
mov ax,0A000h
mov es,ax

;вывод неподвижного квадрата
mov cx,9
rect:
push cx
call draw_box
add y,25
pop cx
loop rect
;начальные координаты и цвет перемещаемого квадрата
xor ax,ax
int 16h
check: ;проверяем какая клавишка нажата
cmp al,31h ;если 1 - то двигать 1-й квадрат
je one
cmp al,32h ;если 2 - то второй...
je two
cmp al,27
je exit

one:
mov x,0
mov y,25
mov color,2
jmp redraw
two:
mov x,0
mov y,50
mov color,2

redraw:
;вывести квадрат
call draw_box

;ожидать нажатия клавиши
xor ax,ax
int 16h
;выход по ESC
cmp al,27
je exit

;стереть квадрат
call draw_box

;вычислить новые координаты
add x,2
inc y

jmp redraw

exit:
;восстановить видеорежим
pop ax
xor ah,ah
int 10h

;выход
mov ax,4C00h
int 21h

end entry



 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6


N337
****

Группа: Пользователи
Сообщений: 737
Пол: Мужской

Репутация: -  26  +


Имеет смысл работать с квадратами, как со структурами (зачатки ООП). Текущий квадрат представляется в виде указателя на его структуру (в данном случае это регистр si):
BOX_SIZE	equ 20		;длина стороны квадрата
SCR_WIDTH equ 320 ;ширина экрана

locals

.model small

.stack 2048

.data

;----- структура-квадрат (описание типа) -----
box struc
x dw ?
y dw ?
color db ?
box ends

;----- список квадратов (переменные) -----
box1 box <20, 20, 1>
box2 box <0, 0, 2>

.code

;----- вывод квадрата с заданными координатами и цветом -----
draw_box:
;вичисление смещения в видеобуфере по заданным координатам x и y
;bx = y * SCR_WIDTH + x
mov ax,SCR_WIDTH
mul [si].y
add ax,[si].x
mov bx,ax
mov al,[si].color
;вывод верхней стороны
mov cx,BOX_SIZE-1
@@1:
xor es:[bx],al
inc bx
loop @@1
;вывод правой стороны
mov cx,BOX_SIZE-1
@@2:
xor es:[bx],al
add bx,SCR_WIDTH
loop @@2
;вывод нижней стороны
mov cx,BOX_SIZE-1
@@3:
xor es:[bx],al
dec bx
loop @@3
;вывод правой стороны
mov cx,BOX_SIZE-1
@@4:
xor es:[bx],al
sub bx,SCR_WIDTH
loop @@4
ret

;----- основная программа -----
entry:
;инициализация ds
mov ax,@data
mov ds,ax

;запомнить в стеке номер текущего видеорежима
mov ah,0Fh
int 10h
push ax
;установка видеорежима 320x200x256
mov ax,13h
int 10h

;es:0 -> видеобуфер
mov ax,0A000h
mov es,ax

;выбрать первый квадрат
lea si,box1
;вывести его
call draw_box

;выбрать второй квадрат
lea si,box2

redraw:
;вывести текущий квадрат
call draw_box

;ожидать нажатия клавиши
xor ax,ax
int 16h
;выход по ESC
cmp al,27
je exit

;стереть текущий квадрат
call draw_box

;вычислить новые координаты текущего
add [si].x,2
inc [si].y

jmp redraw

exit:
;восстановить видеорежим
pop ax
xor ah,ah
int 10h

;выход
mov ax,4C00h
int 21h

end entry


--------------------
The idiots are winning.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

Репутация: -  2  +


Цитата(xds @ 20.04.2008 20:21) *

Имеет смысл работать с квадратами, как со структурами (зачатки ООП). Текущий квадрат представляется в виде указателя на его структуру (в данном случае это регистр si):


А если без структур и указателей? Просто нам этого не объясняли..
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #8


N337
****

Группа: Пользователи
Сообщений: 737
Пол: Мужской

Репутация: -  26  +


Структур как таковых в ассемблере нет на самом деле. Запись
box		struc
x dw ?
y dw ?
color db ?
box ends
эквивалентна
x equ word ptr[0]
y equ word ptr [2]
color equ byte ptr [4]


а, mov al,[si].color - на самом деле это mov al,[si+4]. Т. е., si хранит адрес начала области памяти, в которой последовательно хранятся координата x (как word), координата y (как word) и цвет (как байт

Вот эквивалентный вариант без конструкции struc:
BOX_SIZE	equ 20		;длина стороны квадрата
SCR_WIDTH equ 320 ;ширина экрана

locals

.model small

.stack 2048

.data

;----- структура-квадрат (описание типа) -----
x equ word ptr [0]
y equ word ptr [2]
color equ byte ptr [4]

;----- список квадратов (переменные) -----
box1 dw 20
dw 20
db 1

box2 dw 0
dw 0
db 2

.code

;----- вывод квадрата с заданными координатами и цветом -----
draw_box:
;вичисление смещения в видеобуфере по заданным координатам x и y
;bx = y * SCR_WIDTH + x
mov ax,SCR_WIDTH
mul [si].y
add ax,[si].x
mov bx,ax
mov al,[si].color
;вывод верхней стороны
mov cx,BOX_SIZE-1
@@1:
xor es:[bx],al
inc bx
loop @@1
;вывод правой стороны
mov cx,BOX_SIZE-1
@@2:
xor es:[bx],al
add bx,SCR_WIDTH
loop @@2
;вывод нижней стороны
mov cx,BOX_SIZE-1
@@3:
xor es:[bx],al
dec bx
loop @@3
;вывод правой стороны
mov cx,BOX_SIZE-1
@@4:
xor es:[bx],al
sub bx,SCR_WIDTH
loop @@4
ret

;----- основная программа -----
entry:
;инициализация ds
mov ax,@data
mov ds,ax

;запомнить в стеке номер текущего видеорежима
mov ah,0Fh
int 10h
push ax
;установка видеорежима 320x200x256
mov ax,13h
int 10h

;es:0 -> видеобуфер
mov ax,0A000h
mov es,ax

;выбрать первый квадрат
lea si,box1
;вывести его
call draw_box

;выбрать второй квадрат
lea si,box2

redraw:
;вывести текущий квадрат
call draw_box

;ожидать нажатия клавиши
xor ax,ax
int 16h
;выход по ESC
cmp al,27
je exit

;стереть текущий квадрат
call draw_box

;вычислить новые координаты текущего
add [si].x,2
inc [si].y

jmp redraw

exit:
;восстановить видеорежим
pop ax
xor ah,ah
int 10h

;выход
mov ax,4C00h
int 21h

end entry


По другому мне прямо сейчас лень - там больше писанины и меньше разумности.


--------------------
The idiots are winning.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #9


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

Репутация: -  2  +


И снова здраствуйте)

Я добавила переменные box3,..,box9. Осуществила их вывод. По нажатию соответствующей цифровой клавиши 1-й, 2-й или i-й квадрат должен свигаться со своей позиции и изменять положение...Вот только у меня всегда сдвигается 1-й квадрат..Объясните пожалуста, в чём дело?



BOX_SIZE equ 15 ;длина стороны квадрата
SCR_WIDTH equ 320 ;ширина экрана

locals

.model small

.stack 2048

.data

;----- структура-квадрат (описание типа) -----
x equ word ptr [0]
y equ word ptr [2]
color equ byte ptr [4]

;----- список квадратов (переменные) -----
box1 dw 0
dw 10
db 1

box2 dw 20
dw 10
db 2
box3 dw 40
dw 10
db 2
box4 dw 60
dw 10
db 2
box5 dw 80
dw 10
db 2
box6 dw 100
dw 10
db 2

box7 dw 120
dw 10
db 2

box8 dw 140
dw 10
db 2

box9 dw 160
dw 10
db 2

.code

;----- вывод квадрата с заданными координатами и цветом -----
draw_box:
;вичисление смещения в видеобуфере по заданным координатам x и y
;bx = y * SCR_WIDTH + x
mov ax,SCR_WIDTH
mul [si].y
add ax,[si].x
mov bx,ax
mov al,[si].color
;вывод верхней стороны
mov cx,BOX_SIZE-1
@@1:
xor es:[bx],al
inc bx
loop @@1
;вывод правой стороны
mov cx,BOX_SIZE-1
@@2:
xor es:[bx],al
add bx,SCR_WIDTH
loop @@2
;вывод нижней стороны
mov cx,BOX_SIZE-1
@@3:
xor es:[bx],al
dec bx
loop @@3
;вывод правой стороны
mov cx,BOX_SIZE-1
@@4:
xor es:[bx],al
sub bx,SCR_WIDTH
loop @@4
ret

;----- основная программа -----
entry:
;инициализация ds
mov ax,@data
mov ds,ax

;запомнить в стеке номер текущего видеорежима
mov ah,0Fh
int 10h
push ax
;установка видеорежима 320x200x256
mov ax,13h
int 10h

;es:0 -> видеобуфер
mov ax,0A000h
mov es,ax

;выбрать первый квадрат
lea si,box1
;вывести его
call draw_box

lea si,box2
call draw_box
lea si,box3
call draw_box
lea si,box4
call draw_box
lea si,box5
call draw_box
lea si,box6
call draw_box
lea si,box7
call draw_box
lea si,box8
call draw_box
lea si,box9
call draw_box

cmp AL,31h
je one
cmp AL,32h
je two
cmp AL,33h
je three
cmp AL,34h
je four
cmp AL,35h
je five
cmp AL,36h
je six
cmp AL,37h
je seven
cmp AL,38h
je eigth
cmp AL,39h
je nine

one: lea si,box1
jmp redraw
two: lea si,box2
jmp redraw
three: lea si,box3
jmp redraw
four: lea si,box4
jmp redraw
five: lea si,box5
jmp redraw
six: lea si,box6
jmp redraw
seven: lea si,box7
jmp redraw
eigth: lea si,box8
jmp redraw
nine: lea si,box9

redraw:
;вывести текущий квадрат
;call draw_box

;ожидать нажатия клавиши
xor ax,ax
int 16h
;выход по ESC
cmp al,27
je exit

;стереть текущий квадрат
call draw_box

;вычислить новые координаты текущего
add [si].x,2
inc [si].y

jmp redraw

exit:
;восстановить видеорежим
pop ax
xor ah,ah
int 10h

;выход
mov ax,4C00h
int 21h

end entry


 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #10


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

Репутация: -  2  +


Цитата(xds @ 20.04.2008 21:40) *


BOX_SIZE	equ 20		;длина стороны квадрата
SCR_WIDTH equ 320 ;ширина экрана

locals

.model small

.stack 2048

.data

;----- структура-квадрат (описание типа) -----
x equ word ptr [0]
y equ word ptr [2]
color equ byte ptr [4]

;----- список квадратов (переменные) -----
box1 dw 20
dw 20
db 1

box2 dw 0
dw 0
db 2

.code

;----- вывод квадрата с заданными координатами и цветом -----
draw_box:
;вичисление смещения в видеобуфере по заданным координатам x и y
;bx = y * SCR_WIDTH + x
mov ax,SCR_WIDTH
mul [si].y
add ax,[si].x
mov bx,ax
mov al,[si].color
;вывод верхней стороны
mov cx,BOX_SIZE-1
@@1:
xor es:[bx],al
inc bx
loop @@1
;вывод правой стороны
mov cx,BOX_SIZE-1
@@2:
xor es:[bx],al
add bx,SCR_WIDTH
loop @@2
;вывод нижней стороны
mov cx,BOX_SIZE-1
@@3:
xor es:[bx],al
dec bx
loop @@3
;вывод правой стороны
mov cx,BOX_SIZE-1
@@4:
xor es:[bx],al
sub bx,SCR_WIDTH
loop @@4
ret

;----- основная программа -----
entry:
;инициализация ds
mov ax,@data
mov ds,ax

;запомнить в стеке номер текущего видеорежима
mov ah,0Fh
int 10h
push ax
;установка видеорежима 320x200x256
mov ax,13h
int 10h

;es:0 -> видеобуфер
mov ax,0A000h
mov es,ax

;выбрать первый квадрат
lea si,box1
;вывести его
call draw_box

;выбрать второй квадрат
lea si,box2

redraw:
;вывести текущий квадрат
call draw_box

;ожидать нажатия клавиши
xor ax,ax
int 16h
;выход по ESC
cmp al,27
je exit

;стереть текущий квадрат
call draw_box

;вычислить новые координаты текущего
add [si].x,2
inc [si].y

jmp redraw

exit:
;восстановить видеорежим
pop ax
xor ah,ah
int 10h

;выход
mov ax,4C00h
int 21h

end entry




Объясните пожалуста, как на основании такого фрагмента осуществить изменение цвета активного квадратика по нажатию какой-нибудь клавиши?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #11


N337
****

Группа: Пользователи
Сообщений: 737
Пол: Мужской

Репутация: -  26  +


Клавиши "+" и "-" меняют цвет выбранного квадрата:
BOX_SIZE	equ 20		;длина стороны квадрата
SCR_WIDTH equ 320 ;ширина экрана

locals

.model small

.stack 2048

.data

;----- структура-квадрат (описание типа) -----
x equ word ptr [0]
y equ word ptr [2]
color equ byte ptr [4]

;----- список квадратов (переменные) -----
boxes dw 30
dw 30
db 1

dw 40
dw 40
db 2

dw 50
dw 50
db 3

dw 60
dw 60
db 4

dw 70
dw 70
db 5

dw 80
dw 80
db 6

dw 90
dw 90
db 7

dw 100
dw 100
db 8

dw 110
dw 110
db 9

.code

;----- вывод квадрата с заданными координатами и цветом -----
draw_box:
;вичисление смещения в видеобуфере по заданным координатам x и y
;bx = y * SCR_WIDTH + x
mov ax,SCR_WIDTH
mul [si].y
add ax,[si].x
mov bx,ax
mov al,[si].color
;вывод верхней стороны
mov cx,BOX_SIZE-1
@@1:
xor es:[bx],al
inc bx
loop @@1
;вывод правой стороны
mov cx,BOX_SIZE-1
@@2:
xor es:[bx],al
add bx,SCR_WIDTH
loop @@2
;вывод нижней стороны
mov cx,BOX_SIZE-1
@@3:
xor es:[bx],al
dec bx
loop @@3
;вывод правой стороны
mov cx,BOX_SIZE-1
@@4:
xor es:[bx],al
sub bx,SCR_WIDTH
loop @@4
ret

;----- основная программа -----
entry:
;инициализация ds
mov ax,@data
mov ds,ax

;запомнить в стеке номер текущего видеорежима
mov ah,0Fh
int 10h
push ax
;установка видеорежима 320x200x256
mov ax,13h
int 10h

;es:0 -> видеобуфер
mov ax,0A000h
mov es,ax

;для начала, вывести все квадраты
lea si,boxes
push si
mov cx,9
init_box:
push cx
call draw_box
add si,5
pop cx
loop init_box
pop si

get_key:
;ожидать нажатия клавиши
xor ax,ax
int 16h
;выход по ESC
cmp al,27
je exit
;"+" - выбрать следующий цвет для текущего квадрата
cmp al,'+'
je inc_color
;"-" - выбрать предыдущий цвет для текущего квадрата
cmp al,'-'
je dec_color
;нажата ли клавиша с цифрой?
cmp al,'1'
jb non_digit
cmp ah,'9'
jbe sel_square
non_digit:
;нажата ли клавиша со стрелкой?
cmp ax,4800h
je up
cmp ax,4B00h
je left
cmp ax,4D00h
je right
cmp ax,5000h
je down
jmp get_key

redraw:
;вывести текущий квадрат
call draw_box
jmp get_key

;выбор крадрата по нажатию клавиши с цифрой '1'-'9'
sel_square:
sub al,'1' ;si = (al - '1') * 5
mov ah,5
mul ah
lea si,boxes
add si,ax
jmp get_key

dec_color:
;стереть текущий квадрат
cmp [si].color,1
jbe redraw
call draw_box
dec [si].color
jmp redraw

inc_color:
;стереть текущий квадрат
cmp [si].color,15
jae redraw
call draw_box
inc [si].color
jmp redraw

up:
;стереть текущий квадрат
call draw_box
dec [si].y
jmp redraw

left:
;стереть текущий квадрат
call draw_box
dec [si].x
jmp redraw

right:
;стереть текущий квадрат
call draw_box
inc [si].x
jmp redraw

down:
;стереть текущий квадрат
call draw_box
inc [si].y
jmp redraw

exit:
;восстановить видеорежим
pop ax
xor ah,ah
int 10h

;выход
mov ax,4C00h
int 21h

end entry


--------------------
The idiots are winning.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #12


Гость






скажите а как этот код сделать рабочим для Pascal 7.1 со встроенным assembler?
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 




- Текстовая версия 20.02.2018 9:01
Хостинг предоставлен компанией "Веб Сервис Центр" при поддержке компании "ДокЛаб"