I recently started learning assembly (TASM) and I'm currently learning how to properly change the positions of different shapes.
I have the following code:
.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
There's one thing I don't understand:
When I change the coordinates of the rectangle (XstartS and YstartS), the rectangle's position does not change.
I want the rectangle to be centered and under the square, like this:
Could you explain me a couple of things:
What you see on the screen is an irregular redrawing of the first shape due to a number of errors that I have listed below:
@@TestCmd2: cmp ax, kbArrowDown jne @@TestCmd3 mov dx, [Ystart] add dx, [sqWidth]
Here you need to add the height [sqHeight]
instead of the width [sqWidth]
.
Because for the 1st shape width equals height (it's a square after all), you don't see this error reflected on the screen. But, you made the same error for the 2nd shape where the width is different from the height, and that you will see once the 2nd shape finally gets drawn.
@@TestCmd5: cmp ax, kbEsc (*) jne @@TestCmd1S (*) jae @@GetCmdS (*) invoke Bar, <[sqHeightS], [sqWidthS], [YstartS], [XstartS], [sqColorS] > @@GetCmdS: mov ah, 00h int 16h @@TestCmd1S:
The 2nd bar is never drawn here! If the key is not ESC then you jump to TestCmd1S and if the key is ESC you jump to GetCmdS. The invoke Bar ...
cannot execute.
I have followed your program flow and as it turns out you don't need to test for ESC here at all. You can simply remove the 3 instructions that I've marked with an asterisk (*).
@@TestCmd1S: cmp ax, kbArrowUp jne @@TestCmd2S mov dx, [YstartS] cmp dx, 0 jae @@GetCmdS
The conditional jump jae
here acts like an unconditional jump because of the 'above' condition being always true with the numbers in use! You need the je
instruction here.
Your program contains 8 jmp @@Redraw
instructions and not a single jmp @@RedrawS
!
The top part needs 4 jmp @@Redraw
instructions and the bottom part needs 4 jmp @@RedrawS
instructions.
invoke BarS, <[sqHeightS], [sqWidthS], dx, cx, [sqColor]>
The color is in [sqColorS]
for the 2nd shape.
I'm confident that once the above errors are corrected the program will work as intended (moving rectangles).
[Late catch]
You don't need 2 identical procedures Bar and BarS in your program!
Instead of
invoke Bar, <[sqHeight], [sqWidth], dx, cx, [sqColor]>
invoke BarS, <[sqHeightS], [sqWidthS], dx, cx, [sqColorS]>
you can safely use
invoke Bar, <[sqHeight], [sqWidth], dx, cx, [sqColor]>
invoke Bar, <[sqHeightS], [sqWidthS], dx, cx, [sqColorS]>