Plot pixel at Linear Frame Buffer

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
Elja98
Posts: 15
Joined: Fri Aug 16, 2013 1:38 pm

Plot pixel at Linear Frame Buffer

Post by Elja98 »

Hello all,

This is my first post in this forum. I'm creating an operating system and I'm pretty successful until now. I'm using VESA and want to plot a pixel. I can find examples for doing it in C, but the problem is I'm still using assembly. How to plot a pixel in assembly? I'm using mode 117h (1024 x 768 16bit color). I already found the address of the linear frame buffer. I hope somebody can help.

Thanks in advance.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Plot pixel at Linear Frame Buffer

Post by Brendan »

Hi,
Elja98 wrote:This is my first post in this forum. I'm creating an operating system and I'm pretty successful until now. I'm using VESA and want to plot a pixel. I can find examples for doing it in C, but the problem is I'm still using assembly. How to plot a pixel in assembly? I'm using mode 117h (1024 x 768 16bit color). I already found the address of the linear frame buffer. I hope somebody can help.
Find the offset in the LFB for the start of the line, using "Y * bytes_per_line". For example (assuming EAX contains the Y co-ord):

Code: Select all

    mul dword [bytes_per_line]      ;edx:eax = y * bytes_per_line
Then multiply the X co-ord by the bytes per pixel (2) to find the offset of the pixel on the line; then add it to your "offset for the start of the line". For example (assuming EBX contains the X co-ord):

Code: Select all

    lea edx,[ebx*2+eax]             ;edx = y * bytes_per_line + x * bytes_per_pixel
Then add the address of the LFB. Hopefully you're using paging to map it at a fixed address, so the above instruction can be "lea edx,[ebx*2+eax+LFB_address]". Otherwise you need a whole new instruction for it:

Code: Select all

    add edx,[LFB_address]           ;edx = LFB_address + y * bytes_per_line + x * bytes_per_pixel
Once you've got the right address calculated, store the colour at the address. For example (assuming CX contains the colour):

Code: Select all

    mov [edx],cx
Of course hopefully you're using paging and can combine this with the "lea edx,[ebx*2+eax+LFB_address]", and do "mov [ebx*2+eax+LFB_address],cx" instead.

Basically, if your LFB isn't at a fixed address you might get something like this:

Code: Select all

;Input:
;   eax = Y co-ord
;   ebx = X co-ord
;   cx = colour
;
;Output
;   none
;
;Trashed
;  edx, eax

plotPixel:
    mul dword [bytes_per_line]      ;edx:eax = y * bytes_per_line
    lea edx,[ebx*2+eax]             ;edx = y * bytes_per_line + x * bytes_per_pixel
    add edx,[LFB_address]           ;edx = LFB_address + y * bytes_per_line + x * bytes_per_pixel
    mov [edx],cx                    ;Set the pixel's colour
    ret
And if your LFB is at a fixed address you might get something like this:

Code: Select all

;Input:
;   eax = Y co-ord
;   ebx = X co-ord
;   cx = colour
;
;Output
;   none
;
;Trashed
;  edx, eax

plotPixel:
    mul dword [bytes_per_line]      ;edx:eax = y * bytes_per_line
    mov [ebx*2+eax+LFB_address],cx  ;Set the pixel's colour
    ret
Now; in both cases the code is relatively small, so the call/ret will add significant overhead. For this reason it'd be better to implement it as a macro.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Elja98
Posts: 15
Joined: Fri Aug 16, 2013 1:38 pm

Re: Plot pixel at Linear Frame Buffer

Post by Elja98 »

Thanks for your quick reply Brendan! Such an easy answer for something I worked days on :oops: Thanks for your help
Elja98
Posts: 15
Joined: Fri Aug 16, 2013 1:38 pm

Re: Plot pixel at Linear Frame Buffer

Post by Elja98 »

I tested your code but unfortunately it doesn't work. Is there something that I have to do with the GDT? Or anything I have to setup to make your code work. Here's my code for now:

My 16 bits code:

Code: Select all

mov	ax, 4F02h			;Set video mode
mov	bx, 117h				;1024 x 768 16 bpp
or	bx, 4000h			;Use Linear Frame Buffer
int	10h

mov	ax, 4F01h			;Get mode information
mov	cx, 117h				;Of mode 117h
mov	di, buffer		
int	10h
	
mov	ax, WORD [buffer+2Ah]	;Get location of Linear Frame Buffer
mov	WORD [loc_lfb], ax		;Save it
mov	ax, WORD [buffer+32h]	;Get Bytes Per Scanline
mov	WORD [BPS], ax		;Save it
After that I enter 32 bits mode and use this:

Code: Select all

mov	eax, 1				;X = 1, Y = 1
mov	ebx, 1
mov	cx, 0000011111100000b		;Color = green

PlotPixel:
mul	WORD [BPS]			;eax = Y * BytesPerScanline
lea	edx, [ebx*2+eax]			;edx = X * 2 + Y * BytesPerScanline
add	edx, [loc_lfb]			;edx = (X * 2 + Y * BytesPerScanline) + LFB (0xE000 bochs)
mov	[edx], cx				;Plot it
Again, Thanks in advance
jnc100
Member
Member
Posts: 775
Joined: Mon Apr 09, 2007 12:10 pm
Location: London, UK
Contact:

Re: Plot pixel at Linear Frame Buffer

Post by jnc100 »

Isn't the LFB at offset 0x28 within the structure? And 4 bytes long?

Regards,
John.
Elja98
Posts: 15
Joined: Fri Aug 16, 2013 1:38 pm

Re: Plot pixel at Linear Frame Buffer

Post by Elja98 »

Yes, but first I did some tests with Bochs to print the dword at 28h. I got 0x0000E000 so I just decided to ignore the first byte and just use 0xE000.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Plot pixel at Linear Frame Buffer

Post by Combuster »

Your print function is wrong. The correct answer is 0xE0000000 (stored as 00 00 00 E0), not 0x0000E000 (which would be 00 E0 00 00 in memory)

Also ignoring one byte is not the same as ignoring two bytes. This business is very, very sensitive to details and I would recommend that you grow some appreciation for that. Tiny mistakes like these will tend to haunt you through your entire OS if left unchecked.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Elja98
Posts: 15
Joined: Fri Aug 16, 2013 1:38 pm

Re: Plot pixel at Linear Frame Buffer

Post by Elja98 »

I'm feeling like a complete idiot right now. I always forget to swap bytes and words when I read hex. I work days on it and after that I find out I have to swap them. But thanks sir!

I changed my code and it works perfect:

Code: Select all

16 bits:
mov	ax, WORD [buffer+28h]
mov	WORD [loc_lfb], ax
mov	ax, WORD [buffer+2Ah]
mov	WORD [loc_lfb+2], ax

32 bits:
PlotPixel:
mul	WORD [BPS]
lea	edx, [ebx*2+eax]
add	edx, [loc_lfb]
mov	[edx], cx

loc_lfb dd 0
Thanks to everybody that helped me :D
h0bby1
Member
Member
Posts: 240
Joined: Wed Aug 21, 2013 7:08 am

Re: Plot pixel at Linear Frame Buffer

Post by h0bby1 »

normally you'd rather plot on a backbuffer in memory and then copying the backbuffer on the vesa framebuffer memory, it avoid flickering or out of sync display, the method is the same than explained above but done to a memory buffer, and with vesa you can also have the backbuffer in video memory if you change the access window with a vesa interupt, you can store your pixel in some part of the video memory that is not displayed, and then swap the start address of display memory to display it and then draw the new pixels in the area that is not displayed, i don't remember all the details of doing that, but it's not very good to draw directly to the display framebuffer, with the vesa memory window change, you can have a backbuffer without the need to copy a backbuffer to video memory
Post Reply