i got a code that that try to pass the VBE LFB address to the protected mode, but can't access the right value, i just dont know the right way to get a real mode saved value in the protected mode (i think theres no problem here) the boot.s:
[BITS 16]
[ORG 0x7C00]
setup_stack:
xor ax, ax; // ax = 0
mov ds, ax; // ds = 0
mov es, ax; // es = ds
mov bx, 0x8000; // stack segment can be any usable memory
mov ss, bx; // stack start 0x80000
mov sp, ax; // stack final 0x8FFFF
cld; // clear direction flag
read_kernel:
mov ah, 00; // reset disk
int 13h; // disk interrupt
mov ax, 0x0000; // register ax [0000]:1000
mov bx, 0x1000; // register bx 0000:[1000]
mov ah, 0x2; // read sector instruction
mov al, 0x3; // sectors to read
mov ch, 0x0; // cylinder
mov cl, 0x2; // local to write
mov dh, 0x0; // head
int 0x13; // call the disk interupter
jmp 0x0000:0x1000; // Jump to kernel
cli; // clear interrupt flag
hlt; // halt
the kernel loads the VBE and after this, the protected mode, kernel.s:
[BITS 16]
[ORG 0x1000]
jmp main_x16;
%include "sys/x16/data.s"; // the GDT table
%include "sys/x16/code/VBE.s" // 512+256 bytes so dont fit the boorloader
main_x16:
call VBE.enable; // its works and here i draw a pixel
call enter_x32; // enter in protected mode ( x32 bits )
enter_x32:
cli; // clear interrupts
lgdt [gdt_descriptor]; // load Global Descriptor Table
mov eax, cr0; // switch to protected mode
or eax, 0x1; // set PE ( Protection Enable ) bit in CR0
mov cr0, eax; // CR0 is a Control Register 0
jmp CODE_SEG:main_x32; // far jump to 32 bit instructions
[BITS 32]
main_x32:
mov eax, DATA_SEG
mov ds, eax;
mov es, eax;
mov ss, eax;
movzx esp, sp
pop edi; LFB address, the value from mode.framebuffer
mov al, 0x0F; the color of the pixel
mov [edi], al
jmp $;
the vbe theres no problem here as i know, and i did simplify the tables as much as i could:
[BITS 16]
VBE:
.signature db "VBE2"; // must be "VESA" to indicate valid VBE support
.version resw 1; // VBE version; high byte is major version, low byte is minor version
.oem resd 1; // segment:offset pointer to OEM
.capabilities resd 1; // bitfield that describes card capabilities
.video_modes resd 1; // segment:offset pointer to list of supported video modes
.video_memory resw 1; // amount of video memory in 64KB blocks
.rest_of_table resb 500 ;... and others values, this block got 512 bytes; and that line is just to simplify the code
.get_info:
mov ah, 4Fh; Super VGA support
mov al, 00h; Return Super VGA information
mov di, VBE; Pointer to buffer
int 0x10;
ret
.enable:
call VBE.get_info;
call mode.get_info;
call mode.set;
.draw:
;Assume first window is valid
mov ax, WORD [es:mode + 08h]
mov es, ax
;Example of how to change the window
mov ax, 4f05h
xor bx, bx
mov dx, 5 ;This is granularity units
int 10h
;here i can draw a pixel with no problem
mov edi, [mode.framebuffer]; framebuffer address
push edi; save edi for pm
add edi, 180054; pixel address
mov al,0x0F; the color of the pixel
mov [edi], al
ret
mode:
.attributes resw 1; // deprecated, only bit 7 should be of interest to you, and it indicates the mode supports a linear frame buffer.
.window_a resb 1; // deprecated
.window_b resb 1; // deprecated
.granularity resw 1; // deprecated; used while calculating bank numbers
.window_size resw 1;
.segment_a resw 1;
.segment_b resw 1;
.win_func_ptr resd 1; // deprecated; used to switch banks from protected mode without returning to real mode
.pitch resw 1; // number of bytes per horizontal line
.width resw 1; // width in pixels
.height resw 1; // height in pixels
.w_char resb 1; // unused...
.y_char resb 1; // ...
.planes resb 1;
.bpp resb 1; // bits per pixel in this mode
.banks resb 1; // deprecated; total number of banks in this mode
.memory_model resb 1;
.bank_size resb 1; // deprecated; size of a bank, almost always 64 KB but may be 16 KB...
.image_pages resb 1;
.reserved0 resb 1;
.red_mask resb 1;
.red_position resb 1;
.green_mask resb 1;
.green_position resb 1;
.blue_mask resb 1;
.blue_position resb 1;
.reserved_mask resb 1;
.reserved_position resb 1;
.direct_color_attributes resb 1;
.framebuffer resd 1; // physical address of the linear frame buffer; write here to draw to the screen
.off_screen_mem_off resd 1;
.off_screen_mem_size resw 1; // size of memory in the framebuffer but not being displayed on the screen
.reserved1 resb 206;
.get_info:
mov ax, 4F01h; Return mode information
mov cx, 0x101;[VBE_info.video_modes]; first mode
mov di, mode; Pointer to buffer
int 0x10;
ret
.set:
mov ah, 0
mov ax, 0x4F02
mov ebx, [VBE.video_modes]; estore de modes pointer at ebx to can access as a adress
mov bx, [ebx+8]; 8/2 = 4th mode in the mode array!!!!!!!
int 0x10
ret
The system dont draw a pixel in protected mode, thus real edi
its not the same as in protected.
I can't get the saved edi
, what's the right way to do it?
To answer the title question: The easiest way would be to keep it in a register.
Otherwise, work out the linear address where you store it in memory in real mode, then access the same linear address in protected mode.
(either by simply not modifying SS
at all so the base stays the same, or more usefully by using a flat memory model with SS
base = 0 in the GDT and using offset = that linear address. e.g. by setting ESP to point to the same region of linear / physical memory you were using for a stack in real mode.)