Why is the image displayed twice?

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
PRoX
Posts: 6
Joined: Thu Apr 17, 2025 1:58 am
Libera.chat IRC: PRoX

Why is the image displayed twice?

Post by PRoX »

Hi everyone! I recently wrote a little code that outputs an image from a sequence of bytes. Here's the code:

Code: Select all

[BITS 16]
[ORG 800h]

start:
    mov ax, 0x12
    int 0x10
    
    mov ah, 0x0B
    mov bh, 0x00
    mov bl, 1
    int 0x10
    
    mov ax, 0xA000
    mov es, ax
    xor di, di
    
    mov si, image_data
    mov cx, 32
.draw_image:
    push cx
    mov cx, 32
    rep movsb
    add di, 640-32
    pop cx
    loop .draw_image
    
    mov ah, 0x00
    int 0x16
    
    int 0x19

; Image data
image_data: db 0xff, 0xff, 0xff, 0xff, 0xfe, 0xc9, 0x52, 0x10, 0x01, 0x25, 0x9c, 0xef
            db 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xc6, 0x20, 0x00, 0x00
            db 0x00, 0x00, 0x02, 0x6c, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd7
            db 0x10, 0x02, 0x32, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7d, 0xff, 0xff, 0xff
            db 0xff, 0xff, 0xfc, 0x30, 0x00, 0x7d, 0xed, 0xba, 0x62, 0x00, 0x00, 0x00
            db 0x03, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xb2, 0x00, 0x02, 0xcf, 0xff, 0xff
            db 0xee, 0xa2, 0x00, 0x00, 0x00, 0x2b, 0xff, 0xff, 0xff, 0xfc, 0x20, 0x00
            db 0x08, 0xff, 0xff, 0xfe, 0xa9, 0xdc, 0x20, 0x00, 0x00, 0x02, 0xcf, 0xff
            db 0xff, 0xd3, 0x00, 0x00, 0x2d, 0xff, 0xff, 0xfe, 0x40, 0x5e, 0x80, 0x00
            db 0x00, 0x00, 0x3d, 0xff, 0xfe, 0x70, 0x00, 0x00, 0x9f, 0xff, 0xff, 0xfe
            db 0xc8, 0x9e, 0xd5, 0x10, 0x00, 0x00, 0x07, 0xef, 0xfb, 0x10, 0x00, 0x01
            db 0xdf, 0xff, 0xff, 0xfe, 0xdc, 0xaa, 0xab, 0xa7, 0x30, 0x00, 0x01, 0xbf
            db 0xe6, 0x00, 0x00, 0x04, 0xef, 0xff, 0xff, 0xff, 0xfe, 0xee, 0xcb, 0xaa
            db 0x95, 0x00, 0x00, 0x6e, 0xc2, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff
            db 0xff, 0xd9, 0x65, 0x68, 0x64, 0x00, 0x00, 0x1c, 0x80, 0x00, 0x00, 0x0a
            db 0xff, 0xff, 0xff, 0xfe, 0xd8, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08
            db 0x40, 0x00, 0x00, 0x0b, 0xff, 0xff, 0xff, 0xe8, 0x20, 0x00, 0x00, 0x00
            db 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x1c, 0xff, 0xff, 0xff, 0x80
            db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0b
            db 0xff, 0xff, 0xfe, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
            db 0x00, 0x00, 0x00, 0x0a, 0xff, 0xff, 0xfd, 0x20, 0x00, 0x00, 0x00, 0x00
            db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xff, 0xff, 0xfd, 0x20
            db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04
            db 0xdf, 0xff, 0xfe, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
            db 0x20, 0x00, 0x00, 0x00, 0x5d, 0xff, 0xfe, 0x50, 0x00, 0x00, 0x00, 0x00
            db 0x00, 0x00, 0x00, 0x02, 0x50, 0x00, 0x00, 0x00, 0x05, 0xdf, 0xff, 0x80
            db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x00
            db 0x00, 0x6e, 0xff, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08
            db 0xc2, 0x00, 0x00, 0x00, 0x00, 0x08, 0xef, 0xe4, 0x00, 0x00, 0x00, 0x00
            db 0x00, 0x00, 0x00, 0x1c, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x01, 0xaf, 0xf8
            db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xfb, 0x10, 0x00, 0x00
            db 0x00, 0x00, 0x2c, 0xfc, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xbf
            db 0xfe, 0x70, 0x00, 0x00, 0x00, 0x00, 0x05, 0xee, 0x30, 0x00, 0x00, 0x00
            db 0x00, 0x00, 0x07, 0xef, 0xff, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f
            db 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0xff, 0xff, 0xfc, 0x20, 0x00
            db 0x00, 0x00, 0x00, 0x2c, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xff
            db 0xff, 0xff, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa0, 0x00, 0x00, 0x00
            db 0x00, 0x00, 0x08, 0xff, 0xff, 0xff, 0xfc, 0x30, 0x00, 0x00, 0x00, 0x00
            db 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xef, 0xff, 0xff, 0xff, 0xd7
            db 0x10, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf
            db 0xff, 0xff, 0xff, 0xfe, 0xc6, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x6b
            db 0x30, 0x00, 0x00, 0x5e, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xc9, 0x52, 0x10
            db 0x01, 0x25, 0x9c, 0xef, 0x80, 0x00, 0x00, 0x2c
and for some unknown reason it is displayed twice

Screenshot: https://drive.google.com/file/d/1o7NXbr ... sp=sharing
Octocontrabass
Member
Member
Posts: 5805
Joined: Mon Mar 25, 2013 7:01 pm

Re: Why is the image displayed twice?

Post by Octocontrabass »

PRoX wrote: Sun May 11, 2025 5:26 am

Code: Select all

    mov cx, 32
    rep movsb
Your image has 16 bytes per row, but you're writing 32 bytes per row.
User avatar
eekee
Member
Member
Posts: 929
Joined: Mon May 22, 2017 5:56 am
Location: Kerbin
Discord: eekee
Contact:

Re: Why is the image displayed twice?

Post by eekee »

What's ORG 800h for? A DOS COM program would have ORG 100h, a bootsector would likely have ORG 7c00h. A bootsector should also set the segments and set up a stack before calling anything, even INT. Apologies if you're linking this code with other files which handle all that.

Video mode 0x12 is 16-colour VGA which was invented by aliens. ;) I'm not going to explain bitplanes, I barely understand them, but I'm fairly sure you should be setting VGA registers to be sure you're writing to the right bitplane. Or, you could set mode 0x11 instead which is simply 1 bit per pixel. Having said that, mode 0x12 probably defaults to settings which make it act like mode 0x11 by making writes write to all the bitplanes together.

The code to set the background looks fine. (I wonder if that works in mode 0x11? Not sure.)

`add di, 640-32` doesn't look right. There's 640/8=80 bytes in each row, both for the bitplanes of mode 0x12 and the plain screen memory of mode 0x11. I think you want (640-32)/8 or 80-4. That would explain the big gaps between lines.

If you look closely at the screenshot, you'll see the image isn't being drawn twice. The lines on the right side are different to the lines on the left, I think they're meant to be below. I'm starting to get confused, but I think you might want `mov cx, 16` or less.

Just a note that the string instructions like `rep movsb` are not the quickest way to do things on some x86 processors. You mght just as well code a regular loop unless you want extremely compact code.
Kaph — a modular OS intended to be easy and fun to administer and code for.
"May wisdom, fun, and the greater good shine forth in all your work." — Leo Brodie
Post Reply