如何在实模式下保存值并在受保护模式下访问它?

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 设置为指向您在实模式下用于堆栈的同一线性/物理内存区域。)