Search code examples
assemblygraphicsx86tasm

Assembly (TASM) plotting pixel through writing in memory


My old code printed a line in mode 13h with int 10h. I tried to change it from using int 10h into writing in memory but for some reason it doesn't work. I am not familiar with writing in memory so I couldn't guess what is the problem.

Here's the new code:

proc PrintLine
;prints a line
;1.length 
;2.colour
;3.x
;4.y
push bp
mov bp,sp
push ax
push bx
push cx
push dx
push si
mov cx,[bp+10];leangth
mov dx,[bp+4];y
mov al,[bp+8];colour
mov si,[bp+6];x
xor bx,bx
pl:
    push si
    push dx
    push ax
    call PrintPixel
loop pl
pop si
pop dx
pop cx
pop bx
pop ax
pop bp
ret 8
endp PrintLine
proc PrintPixel
;print a pixel through writing into memory
;input:
;1.x
;2.y
;3.colour
;output:
;none
push bp
mov bp,sp
push ax
push bx
push cx
push dx
push di
mov ax,0A000h
mov es,ax
mov ax,[bp+6];y
mov bx,[bp+8];x
mov dl,[bp+4];colour
mov cx,320
mul cx;each line is 320 pixles ax is the number of lines
add ax,bx;bx is the place on the line
mov di,ax
mov [es:di],dl
mov ax, @data  
mov ds, ax
pop di
pop dx
pop cx
pop bx
pop ax
pop bp
ret 6
endp PrintPixel

This is the old code with int 10h:

proc PrintLine
;prints a line
;1.length 
;2.colour
;3.x
;4.y
push bp
mov bp,sp
push ax
push bx
push cx
push dx
push si
mov cx,[bp+10];leangth
mov dx,[bp+4];y
mov al,[bp+8];colour
mov si,[bp+6];x
mov ah,0ch
xor bx,bx
pl:
    push cx
    mov cx,si
    int 10h
    inc si
    pop cx  
loop pl
pop si
pop dx
pop cx
pop bx
pop ax
pop bp
ret 8
endp PrintLine

Solution

  • Your PrintPixel procedure has 2 important problems.

    • Although you preserve a lot of registers, you also use the ES segment register that you don't preserve at all! Why you then re-initialize the DS segment register is a mystery.

    • Because you calculate the video offset address using mul cx you've gotten a dword product in DX:AX, but you kept the pixel color in DL. This can only result in black pixels! They're there but you can't see them.

    Since this question was tagged you can use the versatile imul instruction:

    push bp
    mov  bp, sp
    push ax
    push bx
    push ds
    mov  ax, 0A000h
    mov  ds, ax
    mov  bx, 320      ; Bytes per line in mode 13h
    imul bx, [bp+6]   ; y
    add  bx, [bp+8]   ; x
    mov  al, [bp+4]   ; colour
    mov  [bx], al     <-- No need for any segment override prefix!
    pop  ds
    pop  bx
    pop  ax
    pop  bp
    ret  6
    

    See how much cleaner and shorter this has become?


    With the shift to no longer using the BIOS WritePixel you should also clean-up the PrintLine procedure. It no longer needs e.g. the xor bx, bx.
    Did you know you can push a memory operand directly? Doing so, you'll save a lot of instructions!

     push bp
     mov  bp, sp
     push cx
     mov  cx, [bp+10]       ; length
    pl:
     push word ptr [bp+6]   ; x
     push word ptr [bp+4]   ; y
     push word ptr [bp+8]   ; colour
     call PrintPixel
     loop pl
     pop  cx
     pop  bp
     ret  8