flat assembler
Message board for the users of flat assembler.

Index > OS Construction > Simple example of Vesa driver?[solved]

Author
Thread Post new topic Reply to topic
binary



Joined: 10 Oct 2009
Posts: 29
binary 04 Feb 2012, 21:24
I haven't found a simple vesa code written in asm , can someone show me an example of initializing versa and putting a pixel on screen from protected mode.


Last edited by binary on 05 Feb 2012, 17:55; edited 2 times in total
Post 04 Feb 2012, 21:24
View user's profile Send private message Reply with quote
Dex4u



Joined: 08 Feb 2005
Posts: 1601
Location: web
Dex4u 04 Feb 2012, 23:36
First in real terms, you need to set vesa mode in realmode, than you can use it in PMode

Heres a simple example:
Code:
;************************************
; By Dex
; Assemble with fasm 
; c:\fasm Vesa.asm Vesa.bin
;
;************************************
org 0x7C00 

use16
;****************************
; Realmode startup code.
;****************************

start:
        xor   ax,ax
        mov   ds,ax
        mov   es,ax
        mov   ss,ax
        mov   sp,0x7C00 

;****************************
; Vesa start code.
;****************************

        mov  bx,4112h
        mov  ax,4f01h
        mov  di,Mode_Info       
        mov  cx,bx
        int  10h 
        
        mov  ax,4f02h
        int  10h

;*****************************
; Setting up, to enter pmode.
;*****************************

        cli 
        lgdt  [gdtr]
        
        mov   eax, cr0
        or    al,0x1 
        mov   cr0,eax
 
        jmp   0x10: protected

;*****************************
; Pmode. Wink
;*****************************

use32
protected:
        mov   ax,0x8 
        mov   ds,ax
        mov   es,ax
        mov   ss,ax
        mov   esp,0x7C00
;*****************************
; Turn floppy off.
;*****************************

        mov   dx,3F2h
        mov   al,0
        out   dx,al

;*****************************
; Do we have 32 BitsPerPixel.
;*****************************

        cmp   byte[ModeInfo_BitsPerPixel],32
        jne   Letsloop 

;*****************************
; fade background screen.
;*****************************

fade_screen:
        mov   edx,[ModeInfo_PhysBasePtr]
        mov   edi,edx
        xor   eax,eax
        mov   al,0xc5          
        xor   ebx,ebx
        mov   bl,195 
DoLoop:    
        mov   cx,640*2 
        dec   eax    

        rep   stosd
       
        dec   ebx
        jnz   DoLoop
Letsloop:
        hlt
        jmp   Letsloop

;*************************************
; GDT. 
;*************************************

gdt:        dw    0x0000, 0x0000, 0x0000, 0x0000
sys_data:   dw    0xFFFF, 0x0000, 0x9200, 0x00CF
sys_code:   dw    0xFFFF, 0x0000, 0x9800, 0x00CF
gdt_end:

gdtr:       dw gdt_end - gdt - 1                                          
            dd gdt 


;*************************************
; Make program 510 byte's + 0xaa55
;*************************************
            
times 510- ($-start)  db 0  
dw 0xaa55

;*************************************
; Put uninitialized data here.
;*************************************

;=========================================================;
; Vesa Information Block                         11/12/03 ;
;---------------------------------------------------------;
; DOS EXTREME OS V0.01                                    ;
; by Craig Bamford(Dex).                                  ;
;                                                         ;
;=========================================================;

;============================== VESA MODE INFORMATION ===========================================
Mode_Info:              
ModeInfo_ModeAttributes         rw      1
ModeInfo_WinAAttributes         rb      1
ModeInfo_WinBAttributes         rb      1
ModeInfo_WinGranularity         rw      1
ModeInfo_WinSize                rw      1
ModeInfo_WinASegment            rw      1
ModeInfo_WinBSegment            rw      1
ModeInfo_WinFuncPtr             rd      1
ModeInfo_BytesPerScanLine       rw      1
ModeInfo_XResolution            rw      1
ModeInfo_YResolution            rw      1
ModeInfo_XCharSize              rb      1
ModeInfo_YCharSize              rb      1
ModeInfo_NumberOfPlanes         rb      1
ModeInfo_BitsPerPixel           rb      1
ModeInfo_NumberOfBanks          rb      1
ModeInfo_MemoryModel            rb      1
ModeInfo_BankSize               rb      1
ModeInfo_NumberOfImagePages     rb      1
ModeInfo_Reserved_page          rb      1
ModeInfo_RedMaskSize            rb      1
ModeInfo_RedMaskPos             rb      1
ModeInfo_GreenMaskSize          rb      1
ModeInfo_GreenMaskPos           rb      1
ModeInfo_BlueMaskSize           rb      1
ModeInfo_BlueMaskPos            rb      1
ModeInfo_ReservedMaskSize       rb      1
ModeInfo_ReservedMaskPos        rb      1
ModeInfo_DirectColorModeInfo    rb      1
; VBE 2.0 extensions
ModeInfo_PhysBasePtr            rd      1
ModeInfo_OffScreenMemOffset     rd      1
ModeInfo_OffScreenMemSize       rw      1

;======================================= START OF PROGRAM  ======================================

                                 
                                   
    


This set vesa mode in realmode (640x480 32bpp) and switchs to pmdode.
And fades the screen color.

To write just one pixel you would do this
Code:
mov edi,dword[ModeInfo_PhysBasePtr] ; points to screen
mov eax,0x00ffffff ; color
stosd ; write color whats in eax, to the address thats in edi (screen )
    
this will put one pixel at top left hand corner of screen (will be hard to see)
Some things to note:
If you test in emulator alot now do not support 640x480 32bpp, so you may need to use
Code:
;****************************
; Vesa start code.
;****************************

        mov  bx,4115h
    

instead of
Code:
;****************************
; Vesa start code.
;****************************

        mov  bx,4112h
    
in the above code.
Which is 800x600 32bpp and the about code would need moding to fill the screen right.

Also this code does not enable A20 which means you will only be able to fill 3/4 of screen.


Last edited by Dex4u on 05 Feb 2012, 19:55; edited 1 time in total
Post 04 Feb 2012, 23:36
View user's profile Send private message Reply with quote
binary



Joined: 10 Oct 2009
Posts: 29
binary 05 Feb 2012, 10:55
Thank you ,it works.

One thing I don't understand , ModeInfo_PhysBasePtr is the location of the pixel on screen? i tried modifying the value in ModeInfo_PhysBasePtr and the pixel is in the same position.How do I change the position?
Post 05 Feb 2012, 10:55
View user's profile Send private message Reply with quote
cod3b453



Joined: 25 Aug 2004
Posts: 618
cod3b453 05 Feb 2012, 11:37
ModeInfo_PhysBasePtr is the pointer to the linear frame buffer (LFB) where the screen memory starts. Each pixel is some offset from this value, as follows:
Quote:
offset = ((y * ModeInfo_XResolution) + x) * (bpp / 8 )

So to write a 32bpp pixel at (x,y) you'd write to address:
Quote:
ModeInfo_PhysBasePtr + (((y * ModeInfo_XResolution) + x) * 4)
Code:
mov edi,dword [ModeInfo_PhysBasePtr]

mov eax,dword [ModeInfo_XResolution]  ; eax = ScreenWidth
mov ebx,dword [y]                        ; ebx = y
xor edx,edx                                ; edx = 0
mul ebx                                    ; (edx:)eax = y * ScreenWidth
add eax,dword [x]                  ; eax = (y * ScreenWidth) + x

mov dword [edi+4*eax],0x00FFFFFF   ; ModeInfo_PhysBasePtr + ((y * ScreenWidth) + x) * 4    
Post 05 Feb 2012, 11:37
View user's profile Send private message Reply with quote
binary



Joined: 10 Oct 2009
Posts: 29
binary 05 Feb 2012, 12:42
Thanks for the formula and clarification , I tried that code and for some reason the pixel doesn't show up on screen.I'm using 1024 /768 resolution


I also tried like this:
Code:

mov edi,dword [ModeInfo_PhysBasePtr]

mov eax,dword [ModeInfo_XResolution]    ; eax = ScreenWidth
mov ebx,dword 20                      ; ebx = y
xor edx,edx                             ; edx = 0
mul ebx                                 ; (edx:)eax = y * ScreenWidth
add eax,dword 20


mov ebx,dword 4
xor edx,edx
mul ebx
add eax,edi


mov dword [eax],0x00FFFFFF  
    





Code:

;************************************
; By Dex
; Assemble with fasm 
; c:\fasm vesa.asm vesa.bin
;
;************************************

  use16
  org 7C00h
;****************************
; Realmode startup code.
;****************************

; a20
 in al, 0x92
or al, 2
out 0x92, al


start:
        push  cs
        pop   ds
        push  ds
        pop   es

;****************************
; Vesa start code.
;****************************

        mov  bx,4118h
        mov  ax,4f01h
        mov  di,Mode_Info       
        mov  cx,bx
        int  10h 
        
        mov  ax,4f02h
        int  10h

;*****************************
; Setting up, to enter pmode.
;*****************************

        cli 
        lgdt  [gdtr]
        
        mov   eax, cr0
        or    al,0x1 
        mov   cr0,eax
 
        jmp   0x10: protected

;*****************************
; Pmode. Wink
;*****************************

use32
protected:
        mov   ax,0x8 
        mov   ds,ax
        mov   es,ax
        mov   ss,ax
;*****************************
; Turn floppy off.
;*****************************

        mov   dx,3F2h
        mov   al,0
        out   dx,al

; print pixel

mov edi,dword [ModeInfo_PhysBasePtr]

mov eax,dword [ModeInfo_XResolution]    ; eax = ScreenWidth
mov ebx,dword 20                      ; ebx = y
xor edx,edx                             ; edx = 0
mul ebx                                 ; (edx:)eax = y * ScreenWidth
add eax,dword 20

mov dword [edi+4*eax],0x00FFFFFF

;mov edi,dword[edi+4*eax] ; points to screen
;mov eax,0x00aabbcc ; color
;stosd ; write color whats in eax, to the address thats in edi (screen )




 hlt
;*************************************
; GDT. 
;*************************************

gdt:        dw    0x0000, 0x0000, 0x0000, 0x0000
sys_data:   dw    0xFFFF, 0x0000, 0x9200, 0x00CF
sys_code:   dw    0xFFFF, 0x0000, 0x9800, 0x00CF
gdt_end:

gdtr:       dw gdt_end - gdt - 1                                          
            dd gdt 




;============================== VESA MODE INFORMATION ===========================================
Mode_Info:              
ModeInfo_ModeAttributes         rw      1
ModeInfo_WinAAttributes         rb      1
ModeInfo_WinBAttributes         rb      1
ModeInfo_WinGranularity         rw      1
ModeInfo_WinSize                rw      1
ModeInfo_WinASegment            rw      1
ModeInfo_WinBSegment            rw      1
ModeInfo_WinFuncPtr             rd      1
ModeInfo_BytesPerScanLine       rw      1
ModeInfo_XResolution            rw      1024
ModeInfo_YResolution            rw      1
ModeInfo_XCharSize              rb      1
ModeInfo_YCharSize              rb      1
ModeInfo_NumberOfPlanes         rb      1
ModeInfo_BitsPerPixel           rb      1
ModeInfo_NumberOfBanks          rb      1
ModeInfo_MemoryModel            rb      1
ModeInfo_BankSize               rb      1
ModeInfo_NumberOfImagePages     rb      1
ModeInfo_Reserved_page          rb      1
ModeInfo_RedMaskSize            rb      1
ModeInfo_RedMaskPos             rb      1
ModeInfo_GreenMaskSize          rb      1
ModeInfo_GreenMaskPos           rb      1
ModeInfo_BlueMaskSize           rb      1
ModeInfo_BlueMaskPos            rb      1
ModeInfo_ReservedMaskSize       rb      1
ModeInfo_ReservedMaskPos        rb      1
ModeInfo_DirectColorModeInfo    rb      1
; VBE 2.0 extensions
ModeInfo_PhysBasePtr            rd      20
ModeInfo_OffScreenMemOffset     rd      1
ModeInfo_OffScreenMemSize       rw      1






times 510-($-$$) db 0
dw 0xAA55
    
Post 05 Feb 2012, 12:42
View user's profile Send private message Reply with quote
cod3b453



Joined: 25 Aug 2004
Posts: 618
cod3b453 05 Feb 2012, 13:15
First thing I noticed is you have corrupted the ModeInfo definition rw reserves words, so you need to put those values back to 1. This table is overwritten by the int 0x10 ax = 0x4F01 mode info BIOS call, so you can't store any data here; the actual resolution is determined by the value you give in bx for the int 0x10 ax = 0x4F02 call. (This is defined in VBE2 see http://www.ctyme.com/intr/rb-0275.htm)
Post 05 Feb 2012, 13:15
View user's profile Send private message Reply with quote
binary



Joined: 10 Oct 2009
Posts: 29
binary 05 Feb 2012, 15:34
After that correction is still not working.I don't understand what is causing the problem.
Post 05 Feb 2012, 15:34
View user's profile Send private message Reply with quote
cod3b453



Joined: 25 Aug 2004
Posts: 618
cod3b453 05 Feb 2012, 16:06
I'm not sure how it managed to compile before but I moved the table memory after the boot sector and corrected the size of the ModeInfo_XResolution (my mistake):
Code:
;************************************
; By Dex 
; Assemble with fasm  
; c:\fasm vesa.asm vesa.bin 
; 
;************************************ 

  use16 
  org 7C00h 
;**************************** 
; Realmode startup code. 
;**************************** 

; a20 
 in al, 0x92 
or al, 2 
out 0x92, al 


start:
        push  cs
        pop   ds 
        push  ds 
        pop   es

;**************************** 
; Vesa start code. 
;**************************** 

        mov  bx,4118h
        mov  ax,4f01h 
        mov  di,Mode_Info        
        mov  cx,bx 
        int  10h  
         
        mov  ax,4f02h 
        int  10h 

;***************************** 
; Setting up, to enter pmode. 
;***************************** 

        cli  
        lgdt  [gdtr] 
         
        mov   eax, cr0 
        or    al,0x1  
        mov   cr0,eax 
  
        jmp   0x10: protected 

;***************************** 
; Pmode. Wink 
;*****************************
use32 
protected: 
        mov   ax,0x8  
        mov   ds,ax 
        mov   es,ax 
        mov   ss,ax 
;***************************** 
; Turn floppy off. 
;***************************** 

        mov   dx,3F2h 
        mov   al,0 
        out   dx,al 

; print pixel 

mov edi,dword [ModeInfo_PhysBasePtr] 

movzx eax,word [ModeInfo_XResolution]    ; eax = ScreenWidth
mov ebx,dword 20                      ; ebx = y 
xor edx,edx                             ; edx = 0 
mul ebx                                 ; (edx:)eax = y * ScreenWidth 
add eax,dword 20 

mov dword [edi+4*eax],0x00FFFFFF 

;mov edi,dword[edi+4*eax] ; points to screen 
;mov eax,0x00aabbcc ; color 
;stosd ; write color whats in eax, to the address thats in edi (screen ) 




 hlt 
;************************************* 
; GDT.  
;************************************* 

gdt:        dw    0x0000, 0x0000, 0x0000, 0x0000 
sys_data:   dw    0xFFFF, 0x0000, 0x9200, 0x00CF 
sys_code:   dw    0xFFFF, 0x0000, 0x9800, 0x00CF 
gdt_end: 

gdtr:       dw gdt_end - gdt - 1                                           
            dd gdt  

times 510-($-$$) db 0
dw 0xAA55

;============================== VESA MODE INFORMATION ===========================================
Mode_Info:               
ModeInfo_ModeAttributes         rw      1 
ModeInfo_WinAAttributes         rb      1 
ModeInfo_WinBAttributes         rb      1 
ModeInfo_WinGranularity         rw      1 
ModeInfo_WinSize                rw      1 
ModeInfo_WinASegment            rw      1 
ModeInfo_WinBSegment            rw      1 
ModeInfo_WinFuncPtr             rd      1 
ModeInfo_BytesPerScanLine       rw      1 
ModeInfo_XResolution            rw      1
ModeInfo_YResolution            rw      1 
ModeInfo_XCharSize              rb      1 
ModeInfo_YCharSize              rb      1 
ModeInfo_NumberOfPlanes         rb      1 
ModeInfo_BitsPerPixel           rb      1 
ModeInfo_NumberOfBanks          rb      1 
ModeInfo_MemoryModel            rb      1 
ModeInfo_BankSize               rb      1 
ModeInfo_NumberOfImagePages     rb      1 
ModeInfo_Reserved_page          rb      1 
ModeInfo_RedMaskSize            rb      1 
ModeInfo_RedMaskPos             rb      1 
ModeInfo_GreenMaskSize          rb      1 
ModeInfo_GreenMaskPos           rb      1 
ModeInfo_BlueMaskSize           rb      1 
ModeInfo_BlueMaskPos            rb      1 
ModeInfo_ReservedMaskSize       rb      1 
ModeInfo_ReservedMaskPos        rb      1 
ModeInfo_DirectColorModeInfo    rb      1 
; VBE 2.0 extensions 
ModeInfo_PhysBasePtr            rd      1
ModeInfo_OffScreenMemOffset     rd      1 
ModeInfo_OffScreenMemSize       rw      1    
This worked on QEMU
Post 05 Feb 2012, 16:06
View user's profile Send private message Reply with quote
binary



Joined: 10 Oct 2009
Posts: 29
binary 05 Feb 2012, 17:08
This works but it prints one pixel yellow and anoter one beside it blue instead of one pixel white
Code:
 mov edi,dword [ModeInfo_PhysBasePtr]

movzx eax,word [ModeInfo_XResolution]    ; eax = ScreenWidth
mov ebx,dword 20                      ; ebx = y
xor edx,edx                             ; edx = 0 
mul ebx                                 ; (edx:)eax = y * ScreenWidth 
add eax,dword 20

mov dword [edi+4*eax],0x00FFFFFF  

    




This works as it should but with 3 insted of 4 like this

Code:
   mov edi,dword [ModeInfo_PhysBasePtr]

mov dword [edi+3*1025],0x00FFFFFF   

    


If I do it like this it doesn't work.

Code:

   mov edi,dword [ModeInfo_PhysBasePtr]

mov eax,dword [ModeInfo_XResolution]    ; eax = ScreenWidth
mov ebx,dword 1                      ; ebx = y
xor edx,edx                             ; edx = 0
mul ebx                                 ; (edx:)eax = y * ScreenWidth
add eax,dword 0

mov ebx,dword 4
xor edx,edx
mul ebx
add eax,edi

mov dword [eax],0x00FFFFFF  


    



If I do it like this it doesn't compile( putting 3 instead of 4 )
Code:
 mov edi,dword [ModeInfo_PhysBasePtr]

movzx eax,word [ModeInfo_XResolution]    ; eax = ScreenWidth
mov ebx,dword 10                      ; ebx = y
xor edx,edx                             ; edx = 0 
mul ebx                                 ; (edx:)eax = y * ScreenWidth 
add eax,dword 10

mov dword [edi+3*eax],0x00FFFFFF  

    


I'm using Qemu too
Post 05 Feb 2012, 17:08
View user's profile Send private message Reply with quote
cod3b453



Joined: 25 Aug 2004
Posts: 618
cod3b453 05 Feb 2012, 17:22
Yes QEMU only supports 24bpp - to support both you'll need another multiply by ModeInfo_BitsPerPixel shifted right by 3 (faster divide by Cool and use [edi+eax].
Post 05 Feb 2012, 17:22
View user's profile Send private message Reply with quote
binary



Joined: 10 Oct 2009
Posts: 29
binary 05 Feb 2012, 17:34
You meant something like this?

Code:

mov edi,dword [ModeInfo_PhysBasePtr]

mov eax,dword [ModeInfo_XResolution]    ; eax = ScreenWidth
mov ebx,dword 1                      ; ebx = y
xor edx,edx                             ; edx = 0
mul ebx                                 ; (edx:)eax = y * ScreenWidth
add eax,dword 0

mov ecx , eax
movzx eax,word [ModeInfo_BitsPerPixel]
mov ebx, ecx
xor edx,edx
mul ebx
shr eax , 3

mov dword [eax],0x00FFFFFF  

    


I tried that and no luck
Post 05 Feb 2012, 17:34
View user's profile Send private message Reply with quote
cod3b453



Joined: 25 Aug 2004
Posts: 618
cod3b453 05 Feb 2012, 17:50
You've missed the base address in edi and ModeInfo_BitsPerPixel is a byte:
Code:
mov edi,dword [ModeInfo_PhysBasePtr] 

movzx eax,word [ModeInfo_XResolution]    ; eax = ScreenWidth 
mov ebx,dword 1                      ; ebx = y 
xor edx,edx                             ; edx = 0 
mul ebx                                 ; (edx:)eax = y * ScreenWidth 
add eax,dword 0 

movzx ebx,byte [ModeInfo_BitsPerPixel] 
shr ebx,3
mul ebx 

mov dword [edi+eax],0x00FFFFFF    
Post 05 Feb 2012, 17:50
View user's profile Send private message Reply with quote
binary



Joined: 10 Oct 2009
Posts: 29
binary 05 Feb 2012, 17:54
thank you
Post 05 Feb 2012, 17:54
View user's profile Send private message Reply with quote
Dex4u



Joined: 08 Feb 2005
Posts: 1601
Location: web
Dex4u 05 Feb 2012, 20:12
I posted the wrong code, i have added the new code above.
Note: vesa of that mode have two different implementations.
Some use 24 bits per pixel others use 32 bits per pixel.
You need to do this
Code:
;*****************************
; Do we have 32 BitsPerPixel.
;*****************************

        cmp   byte[ModeInfo_BitsPerPixel],32
        je      Its32BPP
        cmp   byte[ModeInfo_BitsPerPixel],24
        jne    exitHere
Its24BPP:
       ; Put your 24bpp cod here
       jmp     exitHere
Its32BPP:
       ; Put your 32bpp cod here
exitHere: 
    

Normal you use a screen buffer thats is set to 32bpp say and write all you code as 32bpp, you then only need to check and write the differant buffer to screen code when you write buffer to screen.

Also do not forget about A20, as most emulator do it anyway, its not until you test on real PC you find a problem.
Post 05 Feb 2012, 20:12
View user's profile Send private message Reply with quote
binary



Joined: 10 Oct 2009
Posts: 29
binary 06 Feb 2012, 20:16
For 32 bits I should simply put this?

Code:

mov edi,dword [ModeInfo_PhysBasePtr]

movzx eax,word [ModeInfo_XResolution]    ; eax = ScreenWidth 
mov ebx,dword 4                      ; ebx = y
xor edx,edx                             ; edx = 0 
mul ebx                                 ; (edx:)eax = y * ScreenWidth 
add eax,dword 6

mov dword [edi+eax],0x00FFFFFF  


    


I tried the 24 bit vertion on Qemu and bochs and works on both of them
Post 06 Feb 2012, 20:16
View user's profile Send private message Reply with quote
cod3b453



Joined: 25 Aug 2004
Posts: 618
cod3b453 09 Feb 2012, 19:33
You still need to mulitply:
Code:
mov dword [edi+4*eax]    

If you only want to support 32bit this is fine, otherwise it's easier to use the previous version to support both bodes without having to maintain two versions of the code. This is what I ended up doing so I could test on Virtualbox and QEMU
Post 09 Feb 2012, 19:33
View user's profile Send private message Reply with quote
flash



Joined: 11 Mar 2006
Posts: 55
Location: Cuba
flash 06 Apr 2012, 05:51
Tempting luck, it is possible to make the access code very similar to the one to access vga framebuffer in real mode.
Almost in qemu, all standar vesa modes points linear framebuffer address at 0xf0000000. For this reason, once you have video mode set and in protected mode, works fine:
Code:
          mov     ebx,0xf0000000                   ; points the LFB
          mov     edi,(x + y*mode_width)*Bpp       ; note Bpp means bytes per pixel
          mov     eax,color_code
          mov     [ebx+edi],eax
    

So, essentially your task is to set video mode and take care about screen geometry
Post 06 Apr 2012, 05:51
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.