为什么在这段代码中,当坐标改变时矩形不移动?
Why in this code a rectangle doesn't move when its coordinates are changed?
我最近开始学习组装(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)时,矩形的位置不会改变。
what I have
我希望矩形在正方形下方居中,像这样:
what I need
你能给我解释几件事吗:
- 为什么在这段代码中,当坐标改变时矩形不移动?
- 正确的代码应该是什么样的,以便结果显示在第二个屏幕截图中?
您的程序永远不会绘制第二个形状!
由于我在下面列出的一些错误,您在屏幕上看到的是第一个形状的不规则重绘:
@@TestCmd2:
cmp ax, kbArrowDown
jne @@TestCmd3
mov dx, [Ystart]
add dx, [sqWidth]
此处需要添加高度[sqHeight]
而不是宽度[sqWidth]
。
因为对于第一个形状 width 等于 height,它毕竟是一个正方形,你不会在屏幕上看到这个错误。 但是,您在宽度与高度不同的第二个形状上犯了同样的错误,一旦最终绘制出第二个形状,您就会看到。
@@TestCmd5:
cmp ax, kbEsc (*)
jne @@TestCmd1S (*)
jae @@GetCmdS (*)
invoke Bar, <[sqHeightS], [sqWidthS], [YstartS], [XstartS], [sqColorS] >
@@GetCmdS:
mov ah, 00h
int 16h
@@TestCmd1S:
这里从来没有画过第二根柱子!如果键不是 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 个相同的过程 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]>
我最近开始学习组装(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)时,矩形的位置不会改变。
what I have
我希望矩形在正方形下方居中,像这样:
what I need
你能给我解释几件事吗:
- 为什么在这段代码中,当坐标改变时矩形不移动?
- 正确的代码应该是什么样的,以便结果显示在第二个屏幕截图中?
您的程序永远不会绘制第二个形状!
由于我在下面列出的一些错误,您在屏幕上看到的是第一个形状的不规则重绘:
@@TestCmd2: cmp ax, kbArrowDown jne @@TestCmd3 mov dx, [Ystart] add dx, [sqWidth]
此处需要添加高度[sqHeight]
而不是宽度[sqWidth]
。
因为对于第一个形状 width 等于 height,它毕竟是一个正方形,你不会在屏幕上看到这个错误。 但是,您在宽度与高度不同的第二个形状上犯了同样的错误,一旦最终绘制出第二个形状,您就会看到。
@@TestCmd5: cmp ax, kbEsc (*) jne @@TestCmd1S (*) jae @@GetCmdS (*) invoke Bar, <[sqHeightS], [sqWidthS], [YstartS], [XstartS], [sqColorS] > @@GetCmdS: mov ah, 00h int 16h @@TestCmd1S:
这里从来没有画过第二根柱子!如果键不是 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 个相同的过程 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]>