Search code examples
arraysassemblycolorspixel

Assembly graphic couldn't display right colour from array


Welcome. I could't get values from 2d array. I am trying and trying and it doesn't work. I use NASM 16 DOS

I want to have blue letter E on red backgroung. I only get square random colours. '1' in array is blue,'4' is red. It could be spinned, but it doesn't matter.

I have no idea what is wrong. I'm trying to do this a couple od days.

Here is my code:

    segment .data

    segment .code
..start:
    mov ax, 13h 
    int 10h               ; switch to 320x200 mode

    mov ax, 0a000h        ; The offset to video memory
    mov es, ax            ; We load it to ES through AX,
                          ; because immediate operation
                          ; is not allowed on ES
;;;;;;;;;;;;;;;;;;;;;;
    mov si, T34 ; my array

    mov word [Y_Start], 10 ; Y start line count values in register
    mov word [X_Start], 20 ; X start line
    mov word [Y], 10 ; Y start line
    mov word [X], 20 ; X start line

    mov dx, 4  ; colour (red)
    mov cx, 8 ; loop top counter
    top:
        add word [Y], 1
        push cx ;loop top counter =
        mov cx, 8 ;inside loop counter
        inside:
        add word [X], 1
;//////////////////////////////////////////////      count colour
         push ax  ; remember value before procedure
         push bx
         push cx
         push dx

        mov ax, word [X]
        mov cx,8
        mul cx ;X*8 
        add ax, word[Y] ; X*8 +Y

        mov cx,4
        mul cx ; (X*8+Y)*4


        add ax, si ; tab0 + (X*8+Y)*4

        pop dx  

            mov dx,  ax; colour

            pop cx
            pop bx
            pop ax
;///////////////////////////////////////////        
        mov ax, word [Y]
        mov bx, word [X]
        push ax  ; remember value before procedure
        push bx
        push cx

        call putpixel

        pop cx  ; go back to old values
        pop bx
        pop ax
        loop inside
        mov bx, word [X_Start] ; move to X start
        mov word [X], bx       ;      

        pop cx ;loop top counter

    loop top

;;;;;;;;;;;;;;;;;;;;;;;;;

    xor ah, ah
    int 16h               ; keyboard (wait for key)

    mov ax, 3
    int 10h               ; go to text mode

    mov ax, 4c00h
    int 21h               ; return to DOS, exit code 0

;;;;;;;;;;;;;;;;;;;;;

putpixel:
    push dx               ; mul changes dx too
    mov cx, 320
    mul cx                ; multiply Y (ax) by 320 (one row)
    add ax, bx            ; and add X (bx) (result= dx:ax)
    mov di, ax
    pop dx
    mov [es:di], dx       ; store color/pixel
    ret

;;;;;;;;;;;;;;;;;;;;;;

X_Start DW 0 ; start letter position
Y_Start DW 0
X DW 0 ;current letter position
Y DW 0

T34 DB 1,1,1,1,1,1,1,1
    DB 1,4,4,4,4,4,4,4
    DB 1,4,4,4,4,4,4,4
    DB 1,4,4,4,4,4,4,4
    DB 1,1,1,1,1,1,1,1
    DB 1,4,4,4,4,4,4,4
    DB 1,4,4,4,4,4,4,4
    DB 1,1,1,1,1,1,1,1

Solution

  • I didn't catch your approach, but I can show you how I would do it:

    segment .code
    ..start:
        mov ax, data            ; Initialize DS (needed for .exe-program)
        mov ds, ax
    
        mov ax, 0A000h          ; Segment to video memory
        mov es, ax
    
        mov ax, 13h
        int 10h                 ; Switch to 320x200 mode
    
        mov si, T34             ; DS:SI = letter
        mov bx, [X_Start]
        mov ax, [Y_Start]
        call vector_to_memory
        mov di, ax              ; ES:DI = video memory
        call paint
    
        ; once more
        add word [X_Start], 8   ; That's one small step for a man
        mov si, T34             ; DS:SI = letter
        mov bx, [X_Start]
        mov ax, [Y_Start]
        call vector_to_memory
        mov di, ax              ; ES:DI = video memory
        call paint
    
        xor ah, ah
        int 16h                 ; keyboard (wait for key)
    
        mov ax, 3
        int 10h                 ; go to text mode
    
        mov ax, 4c00h
        int 21h                 ; return to DOS, exit code 0
    
    paint:                      ; Args: DS:SI = letter, ES:DI: video memory
        mov ax, 8
        .l1:
        mov cx, 8               ; repetition count for REP
        rep movsb               ; CX times (one row): [DS:SI] => [ES:DI], SI++, DI++
        add di, (320-8)         ; next row
        sub ax, 1               ; no row left?
        jnz .l1                 ; no: once more
        ret                     ; yes: paint is done, return
    
    vector_to_memory:           ; Args: BX = X, AX = Y
        push dx                 ; mul changes dx too
        mov cx, 320             ; video mode width
        mul cx                  ; DX:AX = AX * CX
        add ax, bx              ; left indentation
        pop dx
        ret                     ; Return: AX = offset in memory
    
    segment .data
    
    T34:
        DB 1,1,1,1,1,1,1,1
        DB 1,4,4,4,4,4,4,4
        DB 1,4,4,4,4,4,4,4
        DB 1,4,4,4,4,4,4,4
        DB 1,1,1,1,1,1,1,1
        DB 1,4,4,4,4,4,4,4
        DB 1,4,4,4,4,4,4,4
        DB 1,1,1,1,1,1,1,1
    
    X_Start DW 10 ; start letter position
    Y_Start DW 20
    
    segment stack stack
        resb 0x1000
    

    HTH