Регистры QEMU и eip уничтожаются после перемещения 0x18 в ds - PullRequest
2 голосов
/ 02 мая 2019

В настоящее время я учусь создавать свой собственный загрузчик.Я смог настроить GDT и войти в защищенный режим.Но когда я попытался переместить 0x18 (третий сегмент в gdt) в ds, большинство моих регистров были уничтожены, и eip получил что-то случайное

Код, который вызывает ошибку: (я уже в защищенном 32-битном режиме)

mov eax, 0x18
mov ds, eax  <--- After this instruction registers are destroyed
mov eax, [0x0000]

Мои записи в GDT:

; GDT null segment                                                                                   
  8 gdt_null:
  9     dq 0
 10 
 11 ; GDT code segment (4GB)
 12 gdt_code:
 13     dw 0xFFFF
 14     dw 0x00
 15     db 0x00
 16     db 10011010b
 17     db 11001111b
 18     db 0x00
 19 
 20 ; GDT data segment (4GB)
 21 gdt_data:
 22     dw 0xFFFF
 23     dw 0x00
 24     db 0x00
 25     db 10010010b
 26     db 11001111b
 27     db 0x00
 28 
 29 ; GDT video segment
 30 gdt_video:
 31     dw 0xFFFF
 32     dw 0x00
 33     dw 0x00
 34     dw 10010010b
 35     db 11001111b
 36     db 0x00

GDB до инструкции:

─── Output/messages ─────────────────────────────────────────────────────────────────────────────────────
─── Assembly ────────────────────────────────────────────────────────────────────────────────────────────
0x00007cf4 ? mov    ds,eax
0x00007cf6 ? mov    eax,ds:0x0
0x00007cfb ? hlt    
0x00007cfc ? or     BYTE PTR [eax+0x65],0x6c
0x00007d00 ? ins    BYTE PTR es:[edi],dx
0x00007d01 ? outs   dx,DWORD PTR ds:[esi]
0x00007d02 ? and    BYTE PTR [edi+0x6f],dl
─── Expressions ─────────────────────────────────────────────────────────────────────────────────────────
─── History ─────────────────────────────────────────────────────────────────────────────────────────────
─── Memory ──────────────────────────────────────────────────────────────────────────────────────────────
─── Registers ───────────────────────────────────────────────────────────────────────────────────────────
   eax 0x00000018       ecx 0x00000002       edx 0x00000080       ebx 0x00000000       esp 0x00002000   
   ebp 0x00000000       esi 0x00000000       edi 0x00000000       eip 0x00007cf4    eflags [ PF ]       
    cs 0x00000008        ss 0x000007e0        ds 0x00000010        es 0x000009e0        fs 0x00000000   

GDB после инструкции:

─── Output/messages ─────────────────────────────────────────────────────────────────────────────────────
─── Assembly ────────────────────────────────────────────────────────────────────────────────────────────
0x0000e05b ? add    BYTE PTR [eax],al
0x0000e05d ? add    BYTE PTR [eax],al
0x0000e05f ? add    BYTE PTR [eax],al
0x0000e061 ? add    BYTE PTR [eax],al
0x0000e063 ? add    BYTE PTR [eax],al
0x0000e065 ? add    BYTE PTR [eax],al
0x0000e067 ? add    BYTE PTR [eax],al
─── Expressions ─────────────────────────────────────────────────────────────────────────────────────────
─── History ─────────────────────────────────────────────────────────────────────────────────────────────
─── Memory ──────────────────────────────────────────────────────────────────────────────────────────────
─── Registers ───────────────────────────────────────────────────────────────────────────────────────────
   eax 0x00000000       ecx 0x00000000       edx 0x00000663       ebx 0x00000000       esp 0x00000000   
   ebp 0x00000000       esi 0x00000000       edi 0x00000000       eip 0x0000e05b    eflags [ ]          
    cs 0x0000f000        ss 0x00000000        ds 0x00000000        es 0x00000000        fs 0x00000000   
    gs 0x00000000   

, как вы видите большинствоиз регистров уничтожены, eip находится где-то еще, и это не должно быть кода в этом месте.Некоторые инструкции, прежде чем я перейду 0x10 в DS, и это работает без проблем.Это ошибка QEMU?Я не хочу попробовать это на моем реальном компьютере, потому что, кто знает, что происходит?У кого-нибудь есть идея?

1 Ответ

3 голосов
/ 02 мая 2019

Причина, по которой регистры сбрасываются, заключается в том, что ваша система трижды вышла из строя и вернулась в реальный режим.CS: IP впоследствии будет 0xf000: e05b, который находится в ПЗУ BIOS.GDB неправильно работает с реальным режимом и отображает инструкции в 0x0000: 0xe05b, потому что не понимает, что регистр сегмента 0xf000 также составляет часть адреса и разбирает инструкции из неправильного расположения памяти.Эта память, кажется, была заполнена нулями.BOCHS - лучший отладчик при отладке такого рода проблем на ранних этапах разработки ОС.BOCHs имеет команду info gdt, которая покажет вам загруженный в данный момент GDT.Если запись повреждена, вам будет легче ее увидеть.

Похоже, вам удалось установить CS регистр селектора (до тройной ошибки). Я предполагаю, что часть вашегоGDT действителен.Мое первое наблюдение состоит в том, что ваш gdt_video дескриптор в GDT размещен неправильно.У вас есть:

; GDT video segment
gdt_video:
    dw 0xFFFF
    dw 0x00
    dw 0x00             ; <------ This needs to be a byte
    dw 10010010b        ; <------ This needs to be a byte
    db 11001111b
    db 0x00

Это должно было быть:

; GDT video segment
gdt_video:
    dw 0xFFFF
    dw 0x00
    db 0x00
    db 10010010b
    db 11001111b
    db 0x00

У вас могут быть другие проблемы, но, исходя из предоставленной информации, это единственное, что я могу наблюдать как неправильное.


Другие наблюдения

  • Неясно, почему вы создали дескриптор gdt_video.Вы сделали его дескриптором данных размером 4 ГБ, таким же, как дескриптор gdt_data.Оба дескриптора, как вы показали здесь, идентичны.Вы могли бы загрузить селектор DS с 0x10.
  • Вы не показываете весь свой код, но я заметил, что перед тройной ошибкой отладчик сказал:

    ss 0x000007e0        ds 0x00000010        es 0x000009e0        fs 0x00000000
    

    Я надеюсь, что вы намереваетесь установить SS ESP ), ES , FS GS в какой-то момент. SS: ESP должен быть установлен перед использованием любых инструкций, которые взаимодействуют со стеком (например: push, pop, call, ret и т. Д.)

...