Search code examples
assemblymemoryx86-16vga

writing directly to video memory


I heard that int 10h, ah = 0Ch is pretty slow, and to get a reasonable speed I would need to go to the memory and put the value into the pixel I want to, I set my video mode to be 13h with int 10h. the call to change the video mode:

mov ah , 0
mov al , 13h
int 10h

and this is the procedure I wrote in order to put a pixel in the given coordinates:

drawFaster proc
    ; bp + 2 - row (dx)
    ; bp + 4 - column (cx)
    ; bp + 6 - color
    mov bp , sp
    pushad
    mov ax , 0A000h - presumably the memory address of the screen
    mov es , ax
    mov ax , [bp + 2]
    mov bx , [bp + 4]
    mov cx , 320
    mul cx

    add ax , bx
    mov di , ax
    mov ax , [bp + 6]

    mov [es:di] , al 

    popad
    ret 6
endp

code that calls the function:

    push bp
    mov ax , 30
    push ax
    mov cx , 50
    push cx
    mov dx , 50
    push dx
    call drawFaster
    pop bp

but for some reason, this yields no results, I don't know if the memory address is incorrect or if something else is. I need your help. Thanks!

The strange thing is that the following piece of code works

mov ax , 0A000H
mov es , ax
mov [es:0] , 30

but the following piece of code doesnt:

mov ax , 0A000H
mov bx , 0
mov es , ax
mov [es:bx] , 30

Solution

  • I found a workaround, but it is probably not the best way to go at it, instead of using es (because it doesnt work)

    I changed the data segment's address to lead to 0A000H,

    and then I change the pixel with mov [di] , al and it works!

    But if you are trying this, be sure to move the data segment's address back to its original place.

    my function in its working state, if anyone is interested:

    drawFaster proc
        ; bp + 2 - row (dx)
        ; bp + 4 - column (cx)
        ; bp + 6 - color
        mov bp , sp ; changing bp to access the stack segment
        ; pushing the values to not lose them in the process of calling the function
        push ax
        push bx
        push cx
        push dx
        mov ax, 0A000h ; 0A000h is the video memory address (for some video modes like 13h)
        mov ds , ax
        mov ax , [bp + 2] ; getting the row ( Y )
        mov bx , [bp + 4] ; getting the column ( X )
        mov cx , 320 ; multiplying the row by 320 to get the offset, and then adding the column
        mul cx
    
        add ax , bx
        mov di , ax
        mov ax , [bp + 6] ; getting the desired color to paint the pixel in 
        mov [di] , al ; changing the color of the chosen pixel with the desired color
        ; changing the data segment's address back to its original state 
        ; VERY CRUCIAL PLEASE DON'T MISS THIS IF YOU DO IT THE SAME WAY
        mov ax , @data
        mov ds, ax
        ; changing the values back to what they were
        pop dx
        pop cx
        pop bx
        pop ax
        ret 6
    endp