Search code examples
assemblyx86-16vga

Why an x86 assembly program does not paint the symbol


I'm a university student and I can't figure out where my mistake is. Here's my assignment to write in x86 assembly language.(I wrote on an INTEL syntax, I use DosBOX to run it).

I've asked a similar question before.

Here's the task.

Fill page 0 of the video memory with any text. In the first line of the screen, display 16 NUL characters (ASCII code 0) with different values of the background attribute (the highest tetrad of the symbol attribute). Press the left button in the first line to select and store the selected color. When the cursor is placed on any character of the remaining lines of the screen, the color of the character will change to the selected one by pressing the left button.

BUT now I face another problem. When I click on the symbol, it does not change color to the selected one. To be honest I'm already confused and do not know how to fix it.

.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 ax, 10b
    jne to_end

    mov ax, 2           ; hide cursor
    int 33h

    shr  cx, 3
    shr  dx, 3
    
    mov  di, dx

    imul di, 160
    add  di, cx
    add  di, cx

    cmp  di, 80
    jg  another_row
first_row:
    mov  al, es:[di]  ; Get the value of the attribute
    mov  style, al      ; Store the color in the style variable
    jmp  to_end         ; Jump to the end of the procedure
another_row:
    mov  al, style
    mov  es:[di], al  ; Change the value of the attribute
to_end:

    mov ax, 1           ; show cursor
    int 33h

    popa
    pop es
    pop ds
    retf
prmaus  endp
Code ends
end start

It is expected that when you put the cursor on the color selects a color, then when you put the cursor on the symbol, it changes color to the selected


Solution

  • At a quick glance I see next errors:

    cmp  di, 80
    jg  another_row
    

    The DI register has an address in the text video memory. A single line comprises 160 bytes. You need to compare to 160 like in:

    cmp  di, 160
    jnb  another_row
    

    Building on the knowledge that DX holds the row index [0,24], checking for the first row is best done using:

    test dx, dx
    jnz  another_row
    
    mov  al, es:[di]  ; Get the value of the attribute
    mov  es:[di], al  ; Change the value of the attribute
    

    This is not what I wrote in my previous answer! The attribute is at es:[di+1]. The +1 is very important. You are erroneously retrieving and overwriting the ASCII field.