我是一个大学生,我不知道我的错误在哪里。这是我的作业,用x86汇编语言编写。(我用INTEL语法编写,我用DosBOX运行它)
用任何文本填充显存的第0页。在屏幕的第一行,显示16个NUL字符(ASCII代码0),背景属性的值不同(符号属性的最高四元组)。在第一行按下左键以选择并存储所选颜色。当光标放置在屏幕其余行的任何字符上时,字符的颜色将通过按向左按钮变为所选的颜色。
但是程序改变了一个符号的颜色,而不是我用光标点击的那个。
.386
Data segment use16
ColorOne db 2fh
ColorMain db 0fh
sym db 100
style db ?
Data ends
Code segment use16
assume cs:Code, ds:Data
start:
mov ax, DATA
mov ds, ax
mov ax, 0B800h
mov es, ax
mov ax, 3 ; 80x35
int 10h
mov bx, 0
xor di, di
; screen fill
loop1:
add di, bx
imul di, 2
mov ah, ColorOne
mov al, 0
stosw
add ColorOne, 10h
inc bx
xor di, di
cmp bx, 16
jl loop1
mov bx, 1
loop2:
mov cx, 0
loop3:
add di, bx
imul di, 80
add di, cx
imul di, 2
mov ah, ColorMain
mov al, sym
stosw
inc cx
xor di, di
cmp cx, 80
jl loop3
inc bx
inc sym
cmp bx, 25
jl loop2
;---------------------------------------------------------
mov ax, 1 ; show cursor
int 33h
mov ax, 0ch
mov cx, 11b ; move and press left button
push es ; save segment status
push cs
pop es
lea dx, prmaus ; set the offset of the event processing procedure from the mouse in the code segment
int 33h ; registration of the address and conditions of the call
pop es
mov ah, 01h ; wait
int 21h ; pause
xor cx,cx ; disconect mouse
mov ax,0ch
int 33h
mov ax, 3 ; clean screen
int 10h
mov ax, 4c00h ; exit
int 21h
;----------------------------------------------------------
prmaus proc far
; saving the contents of registers ds, es
push ds
push es
pusha
push 0b800h
pop es
push Data
pop ds
; algorithm
to_left_mouse:
cmp bx, 1b
jne to_end
mov ax, 2 ; hide cursor
int 33h
first_row:
cmp dx, 0 ; If DX is equal to 0, the mouse is over the first row
jne another_row ; If the mouse is not over the first row, jump to processing other rows
shr cx, 2 ; Shift CX right by 2 bits (divide by 4, because each character takes up 4 bytes)
mov di, cx ; Store the value of CX in DI (for array indexing)
mov bx, es:[di] ; Get the value of the character color in the row
shr bx, 8 ; Shift the color value right by 8 bits
mov bh, bl ; Copy the lower byte to the upper byte of the BH register (to preserve the color)
mov style, bh ; Store the color in the style variable
jmp to_end ; Jump to the end of the procedure
another_row: ; Label for processing other rows of the window
xor di, di ; Zero out the index of the screen buffer
add di, dx ; Add the value of DX to DI (to get the row number)
imul di, 20 ; Multiply the value of DI by 20 (the width of the window in characters)
shr cx, 2 ; Shift CX right by 2 bits (divide by 4, because each character takes up 4 bytes)
add di, cx ; Add the value of CX to DI (to get the column number)
mov ax, es:[di] ; Get the value of the character from the screen buffer
mov al, ah ; Copy the upper byte to the lower byte (to preserve the character)
mov ah, style ; Store the color value in the AH register
stosw ; Save the value in the screen buffer
to_end:
mov ax, 1 ; show cursor
int 33h
popa
pop es
pop ds
retf
prmaus endp
Code ends
end start
我猜想问题可能是两个字节的移位(但另一方面,我尝试了不同的变体,无法得到正确的结果)
shr cx,2 ;将CX右移2位(除以4,因为每个字符占用4个字节)
预计当你点击光标上的颜色时会被选中,而点击符号后,它会变成选中的颜色
1条答案
按热度按时间mccptt671#
评论中的推理是错误的!移动两次只是算术上的捷径。
因为鼠标驱动程序给出CX = 8 * 列,所以我们需要除以8,因为对于显存中的每个字符单元格,我们使用一个单词,所以我们需要乘以2。组合意味着我们需要除以4,而向右双移可以最有效地完成这一操作。
评论中的推理是错误的!乘以20只是一种算术捷径。
因为鼠标驱动程序给出DX = 8 * Row,所以我们需要除以8,而且因为显存中每行字符使用160字节,所以我们需要乘以160。组合意味着我们需要乘以20。
这些操作没有保留任何东西!在后一种情况下,这是为什么“程序改变了一个符号的颜色,而不是我用光标点击的符号”的根本问题。
这些是修复程序
使用
es:[di+1]
可以直接寻址属性字节。imul di, dx, 20
(最好的x86指令之一)执行DI = DX * 20。