为什么x86 32位保护模式寄存器没有给出正确的值?

问题描述 投票:0回答:1

我已经设置了32位保护模式,并尝试通过C和汇编加载全局描述符表(GDT),并尝试通过check_gdt()函数打印不同的寄存器值,其中

    void check_gdt() {
    uint16_t cs, ds, es, fs, gs, ss;

    // Inline assembly to get the values of segment registers
    asm volatile("mov %%cs, %0" : "=r"(cs));    
    asm volatile("mov %%ds, %0" : "=r"(ds));
    asm volatile("mov %%es, %0" : "=r"(es));
    asm volatile("mov %%fs, %0" : "=r"(fs));
    asm volatile("mov %%gs, %0" : "=r"(gs));
    asm volatile("mov %%ss, %0" : "=r"(ss));

    // Print the segment register values
    printf("CS: 0x%x\n", cs);
    printf("DS: 0x%x\n", ds);
    printf("ES: 0x%x\n", es);
    printf("FS: 0x%x\n", fs);
    printf("GS: 0x%x\n", gs);
    printf("SS: 0x%x\n", ss);
}

通过以下方式初始化GDT

void initGdt(){
    gdt_ptr.limit = (sizeof(struct gdt_entry_struct) * 5) - 1;
    gdt_ptr.base = (uint32_t)&gdt_entries;

    setGdtGate(0,0,0,0,0);                      // Null segment                           _________________                   _______________
                                                // Explanation:                          |P|DPL|S|E|DC|RW|A|                 |G|DB|L|Res|    |
    setGdtGate(1,0,0xFFFFFFFF, 0x9A, 0xCF);     // Kernel code segment : access = 0x9A =>|1|00 |1|1|0 |1 |0|, gran = 0xCF => |1|1 |0|0  |1111|
    setGdtGate(2,0,0xFFFFFFFF, 0x92, 0xCF);     // Kernel data segment : access = 0x92 =>|1|00 |1|0|0 |1 |0|, gran = 0xCF => |1|1 |0|0  |1111|                  
                                                //                                        _________________                   _______________
    setGdtGate(3,0,0xFFFFFFFF, 0xFA, 0xCF);     // User code segment   : access = 0xFA =>|1|11 |1|1|0 |1 |0|, gran = 0xCF => |1|1 |0|0  |1111|
    setGdtGate(4,0,0xFFFFFFFF, 0xF2, 0xCF);     // User data segment   : access = 0x9A =>|1|11 |1|0|0 |1 |0|, gran = 0xCF => |1|1 |0|0  |1111|
                                                //                                        -----------------                   ---------------
    gdt_flush((uint32_t) &gdt_ptr);
}



void setGdtGate(uint32_t num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran){

    gdt_entries[num].base_low = (base & 0xFFFF);        // Assign lower base 16 bit
    gdt_entries[num].base_middle = (base >> 16) & 0xFF; // Assign middle base 8 bit
    gdt_entries[num].base_high = (base >> 24) & 0xFF;   // Assign higher base 8 bit

    gdt_entries[num].limit_low = (limit & 0xFFFF);      // Assign lower limit 16 bit
    gdt_entries[num].flags = (limit >> 16) & 0x0F;      // Assign flags lower 4 bit
    gdt_entries[num].flags |= (gran & 0xF0);            // Assign flags upper 4 bit

    gdt_entries[num].access = access;                   // Assign access 8 bit
}

并通过gdt_flush函数将GDT加载到CPU中

gdt_flush:
    ; [esp] Return address (from CALL)
    ; Load the address of the GDT descriptor
    MOV eax, [esp + 4]  ; To load the content of [esp+4] address which is the first argument of gdt_flush((uint32_t) &gdt_ptr)
    LGDT [eax]      ; Load the GDT into the CPU

    MOV ax, 0x10    ; Load kernel data segment selector (0x10)
    MOV ds, ax      ; Set data segment register to kernel data segment
    MOV es, ax      ; Set extra segment register to kernel data segment
    MOV fs, ax      ; Set general-purpose segment to kernel data segment
    MOV gs, ax      ; Set general-purpose segment to kernel data segment
    MOV ss, ax      ; Set stack segment to kernel data segment

    JMP 0x08:.flush ;Far jump to selector 0x08 (code segment) and the address of flush
                    ; Entry 1: Kernel code segment (selector = 0x08)

.flush:
    RET

我期待上面的 gdt 加载

CS : 0x08
DS : 0x10
ES : 0X10
FS : 0X10
GS : 0X10
SS : 0X10

但是为什么我会得到如下错误结果? enter image description here

c assembly x86 osdev gdt
1个回答
0
投票

是的@Jester和@ Michael Petch 都是对的,我的 printf 函数被破坏了。我正在使用 print_hex(cs) ...在 print_hex 所在的地方工作得很好

// 将十六进制数输出到屏幕。无效 print_hex(uint32_t n) { char hex_chars[] = "0123456789ABCDEF"; 打印(“0x”);

for (int i = 28; i >= 0; i -= 4) // process each nibble (4 bits)
{
    putchar(hex_chars[(n >> i) & 0xF]);
} }
© www.soinside.com 2019 - 2024. All rights reserved.