0

I am trying to make a rather simple graphical game in 16-bit x86 assembly. Especially, I want to be able to change the color of a pixel.

I already have an emulated bootloader(qemu) and a piece of code which makes it possible for the game to run on boot so that it can acces certain graphics related components.

After some research I came across the following paper which documents the use of the interupt 10h and thus giving us the following code for changing the color of a pixel:

mov al, 13h     #Desired video mode: graphics mode
mov ah, 0       #Set video mode
int 10h         #Interrupt
mov al, 1100b   #Set color of the pixel(I believe it is light red)
mov cx, 10      #Set x coordinate
mov dx, 20      #Set y coordinate
mov ah, 0ch
int 10h

However I am making the game with AT&T syntax(Education purposes). So I tried and figure it out using that syntax resulting in the following code:

mov $0x00, %ah   #00h interpreted as hexadecimal
mov $0x13, %al   #13h interpreted as hexadecimal  
int $0x10        #10h interpreted as hexadecimal
mov $12, %al     #1100 interpreted as bits    
mov $5, %cx      #Set x coordinate to immediate value 5
mov $5, %dx      #Set y coordinate to immediate value 5
mov $0x0c, %ah   #0ch interpeted as hexadecimal
int $0x10        #10h interpreted as hexadecimal 

However, that does not work and I do not really understand why. Therefore I am hoping someone could point me in the right direction on how to change the color of a pixel.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • `mov $0x00, %ah #00h interpeted as hexadecimal` Aren't you supposed to have `$0x0C` there? – Michael Oct 08 '18 at 13:02
  • Good spot. That is a typo but it does not fix it :) – Just van der Veeken Oct 08 '18 at 13:11
  • 3
    BIOS `int $0x10` calls only work in 16-bit mode, and only with a minimal OS like MS-DOS. They won't work under any modern mainstream OS like Linux or Windows. And they also won't work in a bootloader after switching to 32-bit protected-mode or 64-bit long mode, I think even if you copied the relevant IVT entries to 64-bit IDT entries. – Peter Cordes Oct 08 '18 at 13:11
  • The game is running on boot so I do not have an issue with the OS right? – Just van der Veeken Oct 08 '18 at 13:13
  • 1
    `13h` VGA mode is 320x200 pixels with 256-index palette. Right after `int 10 "set mode"` service with `13h` mode the palette is reset to default DOS palette (quite ugly one), where index "12" really is light red, but you can redefine the palette to custom one, if you wish. ... in modern 64b OS you need different OS services to access some kind of window content (will need probably lot more code, but will cooperate nicely with OS and window manager), or frame buffer directly (usually not easily accessible, and if it is, it often throws off the window manager). – Ped7g Oct 08 '18 at 13:14
  • 2
    @Just: Just updated my last comment. They don't work after switching to 64-bit mode either, even in a freestanding bootloader. You said in the title you're using x86-64. I assumed you meant you were using 64-bit long mode. Do you just leave the x86-64 CPU legacy mode, in 16-bit real mode? Normally when people say x86-64, they mean using long mode or compat mode. – Peter Cordes Oct 08 '18 at 13:15
  • 2
    Right after boot, before switching to 32/64 bit mode, the `int 10h` should work as expected. I will try to dig for one of my answers showing moving square, which did work both as `.com` file under DOS, and as "bootloader". (But what Peter said, your "x86-64" is then wrong, as you are working in the 16 bit world of old 8086/80286, not using anything from x86-64 HW) – Ped7g Oct 08 '18 at 13:15
  • 1
    somewhat related: https://stackoverflow.com/q/42843655/4271923 (would you use NASM as assembler, you could probably just try those out to see if they work for you (they should) and then slowly try to transform that into yours goal) – Ped7g Oct 08 '18 at 13:24
  • @PeterCordes Well you just gave me a better understanding of the different modes so I actually meant right after boot so my "x86-64" is wrong as stated by Ped7g. – Just van der Veeken Oct 08 '18 at 13:25
  • @Ped7g Thanks for the reference. I figured out that indeed I am using a virtual 8086 mode. – Just van der Veeken Oct 08 '18 at 13:28
  • anyway, after re-reading your last state of question, with fixed `ah` value typo, there's nothing wrong about your code. "does not work" is related to parts you don't show (full source, how you build your code, how you turn it into bootable media, in which system you emulate the PC and how give you the media, whether you managed to build+boot some other bootloader code which is known to work for others, etc...). – Ped7g Oct 08 '18 at 15:06
  • 4
    @JustvanderVeeken: Note that using a BIOS function to set a pixel is incredibly inefficient. For that video mode you can write directly to the area starting at `0xA000:0x0000`, where the "offset" part of the address can be calculated as `offset = 320*y + x`. – Brendan Oct 09 '18 at 16:54

0 Answers0