You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

问题根源与修正方案

核心错误点

  1. 鼠标坐标转列号错误:INT 33h返回的CX是鼠标水平像素坐标,80列模式下每列占8像素,正确列号计算应为shr cx, 3(除以8),而非shr cx, 2(除以4)。
  2. 视频内存偏移计算错误:
    • 80列模式下每行占160字节(80字符×2字节/字符),所以行偏移应是imul di, 160,而非imul di, 20。
    • 每个字符占2字节(ASCII码+属性),列号转偏移需乘以2,你之前直接用列号作为内存偏移,导致定位错误。
  3. 属性读取与赋值逻辑错误:
    • 视频内存中字符存储格式是[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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 13:45:15