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

c3frrgcw  于 2023-10-19  发布在  其他
关注(0)|答案(2)|浏览(78)

我得到了一个代码,试图通过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 $;

据我所知,这里没有问题,我尽可能简化了表格:

[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,正确的方法是什么?

y4ekin9u

y4ekin9u1#

回答标题问题:最简单的方法是把它保存在一个文件夹里。
否则,在真实的模式下计算出存储在内存中的线性地址,然后在保护模式下访问相同的线性地址。
(或者根本不修改SS,使基址保持不变,或者更有用的方法是在GDT中使用SS base = 0的平面内存模型,并使用offset =该线性地址。例如,通过将ESP设置为指向您在真实的模式下用于堆栈的相同线性/物理内存区域。

p5fdfcr1

p5fdfcr12#

我有一个和你一样的问题:我加载了一个文件的许多部门到一个 * 内存中的特定地址 *,当切换到保护模式,突然我找不到我加载的信息。我发现这个混乱是由一个包含文件完成的,该文件实际上执行了int 13h以通过lba加载扇区。这是没有在文件的顶部的指令,我发现了痛苦的方式,它需要有太:

[org 0x7c00]
[bits 16]

;... Here the assembly code that
;... loads sectors before
;... switching to protected mode
;... now it works!

相关问题