x86汇编程序点击字符时修改错误符号颜色的问题求助
汇编程序鼠标点击颜色修改问题
我是一名大学生,用Intel语法编写x86汇编程序并在DosBOX中运行,作业要求:
- 填充视频内存0页,首行显示16个带有不同背景属性的NUL字符(ASCII码0),点击首行可选择并保存对应颜色
- 将光标置于其他行任意字符上,点击左键可将该字符颜色改为选中色
实际运行时,程序修改的是鼠标点击位置以外的符号颜色,我怀疑问题出在移位指令shr cx, 2处(注释称每个字符占4字节),尝试多种变体仍未解决,程序代码如下:
.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
问题根源与修正方案
核心错误点
- 鼠标坐标转列号错误:INT 33h返回的CX是鼠标水平像素坐标,80列模式下每列占8像素,正确列号计算应为
shr cx, 3(除以8),而非shr cx, 2(除以4)。 - 视频内存偏移计算错误:
- 80列模式下每行占160字节(80字符×2字节/字符),所以行偏移应是
imul di, 160,而非imul di, 20。 - 每个字符占2字节(ASCII码+属性),列号转偏移需乘以2,你之前直接用列号作为内存偏移,导致定位错误。
- 80列模式下每行占160字节(80字符×2字节/字符),所以行偏移应是
- 属性读取与赋值逻辑错误:
- 视频内存中字符存储格式是
[ASCII字节][属性字节],读取首行属性应直接取es:[di+1],而非移位操作。 - 修改其他行字符时,需保留原ASCII码(AL寄存器),仅替换AH为选中的属性,你之前的
mov al, ah会覆盖原字符。
- 视频内存中字符存储格式是
修正后的关键代码片段
首行颜色选择逻辑修正
first_row: cmp dx, 0 jne another_row shr cx, 3 ; 像素转列号(8像素/列) mov di, cx imul di, 2 ; 列号转内存偏移(2字节/字符) mov bl, es:[di+1] ; 直接读取属性字节 mov style, bl jmp to_end
其他行颜色修改逻辑修正
another_row: xor di, di mov di, dx imul di, 160 ; 行号转内存偏移(160字节/行) shr cx, 3 ; 像素转列号 imul cx, 2 ; 列号转偏移 add di, cx mov al, es:[di] ; 保留原字符ASCII码 mov ah, style ; 替换为选中的属性 mov es:[di], ax ; 直接写入视频内存
内容的提问来源于stack exchange,提问作者Dan
相关产品推荐
相关产品推荐

