OS/OS from Scratch

[OS] 10. 32 bit Enter

jschang 2021. 6. 23. 00:55

서론

이번 강의에서는 32bit protected mode로 진입해 이전 강의에서 만든 코드를 실행해보겠습니다. 해당 Github 강의는 다음과 같습니다.

https://github.com/cfenollosa/os-tutorial/tree/master/10-32bit-enter

 

cfenollosa/os-tutorial

How to create an OS from scratch. Contribute to cfenollosa/os-tutorial development by creating an account on GitHub.

github.com


이론

Pipelining

이 블로그에서 Pipelining에 대해 알기 쉽게 설명해 놓았습니다. Pipelining은 하나의 명령어가 실행되는 도중 동시에 다른 명령어를 시작하는 방식으로 동시에 여러개의 명령어를 실행해 처리량을 올리는 것입니다.

32 bit mode로 진입하는 순서

32bit 모드로 진입하는 순서는 다음과 같습니다.

  1. Interrupt 비활성화
  2. GDT Load
  3. CPU의 control 레지스터 cr0에 값 설정
  4. CPU Pipeline Flush
  5. Segment 레지스터 값 설정
  6. Stack 설정
  7. 32 bit 코드의 Label 실행

코드

32bit_switch.asm

32bit_switch.asm 코드는 위 32bit 모드로 진입하는 순서에 따른 코드입니다.

[bits 16]
switch_to_pm:
    ; 1. Diasble Interrupt 
    cli
    ; 2. Load GDT Descriptor 
    lgdt [gdt_descriptor]
    ; 3. cr0 레지스터를 32bit 모드로 설정 
    mov eax, cr0
    or eax, 0x1 
    mov cr0, eax 
    ; 4. far jump로 pipeline flush
    jmp CODE_SEG:init_pm

[bits 32]
init_pm:
    ; 5. Segment 레지스터 설정 
    mov ax, DATA_SEG
    mov ds, ax
    mov ss, ax 
    mov es, ax 
    mov fs, ax 
    mov gs, ax

    ; 6. Stack 설정 
    mov ebp, 0x90000
    mov esp, ebp

    ; 7. 32bit 모드의 Label 호출 
    call BEGIN_OM

32bit_main.asm

32bit_main.asm은 boot loader와 32bit 모드로 진입하는 main코드가 작성되어 있습니다.

; Boot Loader offset 
[org 0x7c00]

; Stack 설정 
mov bp, 0x90000
mov sp, bp

mov bx, MSG_REAL_MODE 
call print 

call switch_to_pm

%include 'boot_sect_print_function.asm'
%include '32bit_gdt.asm'
%include '32bit_print.asm'
%include '32bit_switch.asm'

[bits 32]
BEGIN_PM:
    mov ebx, MSG_PROT_MODE
    call print_string_pm
    jmp $

MSG_PROT_MODE db 'Loaded 32-bit protected mode', 0x00 
MSG_REAL_MODE db 'Started in 16-bit real mode', 0x00 

; boot sector 
times 510-($-$$)
dw 0xaa55

실행 결과

WSL에서는 GUI환경을 지원하지 않으므로 실행을 위해서는 windows에서 qemu를 실행시키거나 Linux 가상머신에서 실행해야 합니다. Ubuntu에서 실행한 결과는 다음과 같습니다.

실행결과