Недавно я начал изучать сборку (TASM) и в настоящее время изучаю, как правильно менять положение различных фигур.
У меня есть следующий код:
.model small
.stack 100h
.data
; codes returned int 16h ah = 00h
; the arrows we control
kbArrowUp equ 4800h
kbArrowDown equ 5000h
kbArrowLeft equ 4B00h
kbArrowRight equ 4D00h
kbEsc equ 011Bh
; color codes of symbols and points in graphic mode
Red equ 4
Gray equ 7
Blue equ 1
White equ 15
Mode0D_W equ 320 ; screen width in pixels for video mode 0Dh
Mode0D_H equ 200 ; screen height in pixels for video mode 0Dh
Mode0D_C equ 16 ; number of colors for video mode 0Dh
Mode0D_A equ 0A000h ; starting address of video memory for video mode 0Dh
VideoPage db ? ;video page number
Xstart dw 100 ; coordinates of the beginning of the square
Ystart dw 70
sqColor dw 1 ; color of the rendered rectangle
sqWidth dw 40 ; rectangle width
sqHeight dw 40 ; height of the rectangle
XstartS dw 150 ;coordinates of the beginning of the square
YstartS dw 70
sqColorS dw 1 ;color of the rendered rectangle
sqWidthS dw 15 ;rectangle width
sqHeightS dw 80 ;height of the rectangle
; macro to simplify calling procedures with parameters
invoke macro CallProc, Params
IRP P, <Params>
mov ax, P
push ax
endm
call CallProc
endm
.code
main proc
mov ax, @data
mov ds, ax
; setting graphics video mode
mov ax, 000Dh
int 10h
mov ah, 0Fh ; clarification of video mode parameters
int 10h
mov [VideoPage], bh
invoke Bar, <[sqHeight], [sqWidth], [Ystart], [Xstart], [sqColor] >
@@GetCmd:
; waiting for any key
mov ah, 00h
int 16h
;обработка команды
@@TestCmd1:
cmp ax, kbArrowUp
jne @@TestCmd2
mov dx, [Ystart]
cmp dx, 0
je @@GetCmd
dec dx
mov cx, [Xstart]
jmp @@Redraw
@@TestCmd2:
cmp ax, kbArrowDown
jne @@TestCmd3
mov dx, [Ystart]
add dx, [sqWidth]
cmp dx, Mode0D_H
jae @@GetCmd
mov dx, [Ystart]
inc dx
mov cx, [Xstart]
jmp @@Redraw
@@TestCmd3:
cmp ax, kbArrowLeft
jne @@TestCmd4
mov cx, [Xstart]
cmp cx, 0
je @@GetCmd
dec cx
mov dx, [Ystart]
jmp @@Redraw
@@TestCmd4:
cmp ax, kbArrowRight
jne @@TestCmd5
mov cx, [Xstart]
add cx, [sqWidth]
cmp cx, Mode0D_W
jae @@GetCmd
mov cx, [Xstart]
inc cx
mov dx, [Ystart]
jmp @@Redraw
@@TestCmd5:
cmp ax, kbEsc
jne @@TestCmd1S
jae @@GetCmdS
invoke Bar, <[sqHeightS], [sqWidthS], [YstartS], [XstartS], [sqColorS] >
@@GetCmdS:
;ожидание нажатия любой клавиши
mov ah, 00h
int 16h
;обработка команды
@@TestCmd1S:
cmp ax, kbArrowUp
jne @@TestCmd2S
mov dx, [YstartS]
cmp dx, 0
jae @@GetCmdS
dec dx
mov cx, [XstartS]
jmp @@Redraw
@@TestCmd2S:
cmp ax, kbArrowDown
jne @@TestCmd3S
mov dx, [YstartS]
add dx, [sqWidthS]
cmp dx, Mode0D_H
jae @@GetCmdS
mov dx, [YstartS]
inc dx
mov cx, [XstartS]
jmp @@Redraw
@@TestCmd3S:
cmp ax, kbArrowLeft
jne @@TestCmd4S
mov cx, [XstartS]
cmp cx, 0
je @@GetCmdS
dec cx
mov dx, [YstartS]
jmp @@Redraw
@@TestCmd4S:
cmp ax, kbArrowRight
jne @@TestCmd5S
mov cx, [XstartS]
add cx, [sqWidthS]
cmp cx, Mode0D_W
jae @@GetCmdS
mov cx, [XstartS]
inc cx
mov dx, [YstartS]
jmp @@Redraw
@@TestCmd5S:
cmp ax, kbEsc
jne @@GetCmdS
jmp @@StopCmdLoop
@@Redraw:
invoke Bar, <[sqHeight], [sqWidth], [Ystart], [Xstart], 0>
mov ax, [sqColor]
inc ax ;Color++
cmp ax, Mode0D_C ;if (Color>MaxColor)
sbb bx, bx ; Color=1
and ax, bx
cmp ax, 1
adc ax, 0
mov [sqColor], ax
mov [Xstart], cx
mov [Ystart], dx
invoke Bar, <[sqHeight], [sqWidth], dx, cx, [sqColor]>
jmp @@GetCmd
@@RedrawS:
invoke BarS, <[sqHeightS], [sqWidthS], [YstartS], [XstartS], 0>
mov ax, [sqColorS]
inc ax ;Color++
cmp ax, Mode0D_C ;if (Color>MaxColor)
sbb bx, bx ; Color=1
and ax, bx
cmp ax, 1
adc ax, 0
mov [sqColorS], ax
mov [XstartS], cx
mov [YstartS], dx
invoke BarS, <[sqHeightS], [sqWidthS], dx, cx, [sqColor]>
jmp @@GetCmdS
@@StopCmdLoop:
;переключение в текстовый режим
mov ax, 0003h
int 10h
;завершение программы
mov ax, 4C00h
int 21h
main endp
;рисование полосы (залитого прямоугольника)
;на входе:
; color - цвет заливки
; x_pos, y_pos - координаты левого верхнего угла
; x_size, y_size - размеры прямоугольника
;на выходе:
; -
Bar proc color: word, x_pos:word, y_pos: word, x_size: word, y_size: word
push bp ;формирование кадра параметров
mov bp, sp
push ax ;сохранение регистров
push bx
push cx
push dx
push si
push di
mov ah, 0Ch ; настройка параметров для вызова функции 0Ch
mov al, byte ptr color ;цвет точек
mov bh, 0 ;номер видеостраницы
mov dx, y_pos ;строка
mov cx, x_pos ;колонка
mov di, y_size
@@Vertical:
mov cx, x_pos ;колонка
mov si, x_size ;вывести x_size точек в горизонтальной линии
@@Horizontal:
int 10h ;вывести точку
inc cx ;прирастить координату x
dec si
jnz @@Horizontal
inc dx ;переход к следующей горизонтальной линии с
dec di
jnz @@Vertical
pop di ;восстановление рагистров
pop si
pop dx
pop cx
pop bx
pop ax
pop bp
ret 10 ;удаление параметров из стека
Bar endp
BarS proc colorS: word, x_posS:word, y_posS: word, x_sizeS: word, y_sizeS: word
push bp ;формирование кадра параметров
mov bp, sp
push ax ;сохранение регистров
push bx
push cx
push dx
push si
push di
mov ah, 0Ch ; настройка параметров для вызова функции 0Ch
mov al, byte ptr colorS ;цвет точек
mov bh, 0 ;номер видеостраницы
mov dx, y_posS ;строка
mov cx, x_posS ;колонка
mov di, y_sizeS
@@VerticalS:
mov cx, x_posS ;колонка
mov si, x_sizeS ;вывести x_size точек в горизонтальной линии
@@HorizontalS:
int 10h ;вывести точку
inc cx ;прирастить координату x
dec si
jnz @@Horizontal
inc dx ;переход к следующей горизонтальной линии с
dec di
jnz @@Vertical
pop di ;восстановление рагистров
pop si
pop dx
pop cx
pop bx
pop ax
pop bp
ret 10 ;удаление параметров из стека
BarS endp
end main
Одного я не понимаю:
Когда я меняю координаты прямоугольника (XstartS и YstartS), положение прямоугольника не меняется.
Я хочу, чтобы прямоугольник располагался по центру и находился под квадратом, например:
Не могли бы вы объяснить мне пару вещей:
То, что вы видите на экране, — это неправильная перерисовка первой фигуры из-за ряда ошибок, которые я перечислил ниже:
@@TestCmd2: cmp ax, kbArrowDown jne @@TestCmd3 mov dx, [Ystart] add dx, [sqWidth]
Здесь нужно добавить высоту [sqHeight]
вместо ширины [sqWidth]
.
Поскольку для 1-й формы ширина равна высоте (в конце концов, это квадрат), вы не видите отражения этой ошибки на экране. Но вы сделали ту же ошибку для 2-й формы, где ширина отличается от высоты, и вы увидите, как только 2-я фигура наконец будет нарисована.
@@TestCmd5: cmp ax, kbEsc (*) jne @@TestCmd1S (*) jae @@GetCmdS (*) invoke Bar, <[sqHeightS], [sqWidthS], [YstartS], [XstartS], [sqColorS] > @@GetCmdS: mov ah, 00h int 16h @@TestCmd1S:
2-й бар здесь никогда не рисуется! Если ключ не ESC, вы переходите к TestCmd1S, а если ключ ESC, вы переходите к GetCmdS. invoke Bar ...
не может быть выполнен.
Я следил за ходом вашей программы, и, как оказалось, вам вообще не нужно тестировать ESC здесь. Вы можете просто удалить 3 инструкции, которые я пометил звездочкой (*).
@@TestCmd1S: cmp ax, kbArrowUp jne @@TestCmd2S mov dx, [YstartS] cmp dx, 0 jae @@GetCmdS
Условный переход jae
здесь действует как безусловный переход, потому что условие «выше» всегда верно для используемых чисел! Вам нужна инструкция je
здесь.
Ваша программа содержит 8 jmp @@Redraw
инструкций и ни одной jmp @@RedrawS
!
В верхней части нужно 4 jmp @@Redraw
инструкции, а в нижней части нужно 4 jmp @@RedrawS
инструкции.
invoke BarS, <[sqHeightS], [sqWidthS], dx, cx, [sqColor]>
Цвет в [sqColorS]
для 2-й формы.
Я уверен, что после исправления вышеуказанных ошибок программа будет работать как задумано (перемещение прямоугольников).
[Поздний улов]
Вам не нужны 2 одинаковые процедуры Bar и BarS в вашей программе!
Вместо
invoke Bar, <[sqHeight], [sqWidth], dx, cx, [sqColor]>
invoke BarS, <[sqHeightS], [sqWidthS], dx, cx, [sqColorS]>
вы можете безопасно использовать
invoke Bar, <[sqHeight], [sqWidth], dx, cx, [sqColor]>
invoke Bar, <[sqHeightS], [sqWidthS], dx, cx, [sqColorS]>
@EmelianenkoMikhail Этот форум не посвящен отладке внешнего кода. Если у вас есть какие-либо вопросы о программе, вам необходимо опубликовать ее код на этом форуме. У меня сложилось впечатление, что ваш текущий пост уже содержит всю программу. Если с исправлениями текущий код не работает, то объясните подробно чего не хватает...
Я очень благодарен за вашу помощь, но код все еще не работает так, как мне нужно (drive.google.com/file/d/1mb_ivvWwbH9t2IaSurRC8rIAG99EnDqk/…) Буду очень признателен, если вы исправите мои ошибки в документе