如何在实模式下保存值并在受保护模式下访问它?
How i can save a value in real mode and access it in protected?
我得到一个代码,试图将 VBE LFB 地址传递给保护模式,但无法访问正确的值,我只是不知道在保护模式下获取实模式保存值的正确方法
(我认为这里没有问题) 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
内核加载VBE,然后是保护模式,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 $;
据我所知,vbe 在这里没有问题,我确实尽可能地简化了表格:
[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
系统不在保护模式下绘制像素,因此真实edi
它与保护模式不同。
我无法获取已保存的 edi
,正确的方法是什么?
回答标题问题:最简单的方法是将其保存在寄存器中。
否则,在实模式下计算出存储在内存中的线性地址,然后在保护模式下访问相同的线性地址。
(要么根本不修改 SS
使基数保持不变,要么更有效地通过在 GDT 中使用具有 SS
base = 0 的平面内存模型并使用 offset =该线性地址。例如,通过将 ESP 设置为指向您在实模式下用于堆栈的同一线性/物理内存区域。)
我得到一个代码,试图将 VBE LFB 地址传递给保护模式,但无法访问正确的值,我只是不知道在保护模式下获取实模式保存值的正确方法 (我认为这里没有问题) 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
内核加载VBE,然后是保护模式,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 $;
据我所知,vbe 在这里没有问题,我确实尽可能地简化了表格:
[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
系统不在保护模式下绘制像素,因此真实edi
它与保护模式不同。
我无法获取已保存的 edi
,正确的方法是什么?
回答标题问题:最简单的方法是将其保存在寄存器中。
否则,在实模式下计算出存储在内存中的线性地址,然后在保护模式下访问相同的线性地址。
(要么根本不修改 SS
使基数保持不变,要么更有效地通过在 GDT 中使用具有 SS
base = 0 的平面内存模型并使用 offset =该线性地址。例如,通过将 ESP 设置为指向您在实模式下用于堆栈的同一线性/物理内存区域。)