ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [OS] 05. Boot Sector Function
    OS/OS from Scratch 2021. 6. 20. 16:25

    서론

    이번 강의에서는 가장 기본적인 Assembly에서 함수와 같은 역할을 하는 코드를 만들어 보겠습니다. 해당 Github 강의는 다음과 같습니다.

    https://github.com/cfenollosa/os-tutorial/tree/master/05-bootsector-functions-strings

     

    cfenollosa/os-tutorial

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

    github.com


    이론

    Assembly pusha, popa

    pusha는 모든 레지스터에 저장된 값을 Stack에 저장, popa는 Stack에 저장됐던 모든 값을 원래 레지스터 값에 옮겨 원래 상태로 돌려놓는 기능을 합니다. 이와 같은 기능은 현재 상태에서 다른 코드의 기능을 사용하고 싶을 때 활용됩니다.

    Assembly 문자열

    Assembly에서 문자열은 다음과 같이 사용됩니다.

    HELLO:
        db 'Hello World',0x00

    이때 문자열의 끝에는 0x00 Null 문자를 삽입해야 합니다. Assembly에서 newline은 0x0a (Newline) + 0x0d (Carriage Return)으로 이루어집니다. 따라서 이를 출력하기 위한 코드는 다음과 같이 됩니다.

    mov ah, 0x0e
    ; newline 문자 
    mov al, 0x0a
    int 0x10
    ; carriage return 문자 
    mov al, 0x0d
    int 0x10

    Assembly에서 다른 파일 사용

    Assembly 코드에서 다른 파일의 코드를 실행시키기 위해서는 다음 코드를 작성합니다.

    %include “파일명.asm”

    이때 코드에 포함되어 있는 Label의 위치를 주의하며 파일을 불러와야 합니다.

    Assembly ror

    0x1234을 ror 연산하면 값은 0x4123로 변환되고 ror 연산을 반복하면 0x3412, 0x2341, 0x1234로 됩니다.


    코드

    boot_sect_print_function.asm

    문자열을 출력하는 기능, Newline을 출력하는 기능으로 구성되어 있습니다. 먼저 caller에서 print label을 불렀을 때 기존의 상태를 유지하기 위해 상태를 pusha로 저장해 놓습니다. caller 에서 bx에 문자열을 저장해서 넘겨주므로 bx을 시작으로 문자열의 끝인 Null 문자를 만날 때까지 al레지스터에 문자를 옮기고 Interrupt을 발생시키면 됩니다. 이 작업을 반복하는 것이 start label입니다. Null 문자를 만나면 al레지스터에 0x00이 옮겨지므로 done label으로 jump 하고 caller에서 불렀을 때의 상태로 popa 하고 return 합니다.

    ; 문자열 출력
    print:
        pusha
    
    start:
        ; bx가 문자열 시작 주소 
        mov al, [bx]
        cmp al, 0
        je done
    
        mov ah, 0x0e
        int 0x10
    
        add bx, 1
        jmp start
    
    done:
        popa
        ret
    
    ; 줄 바꾸기 
    print_nl:
        pusha
    
        mov ah, 0x0e
        ; newline 문자 
        mov al, 0x0a
        int 0x10
        ; carriage return 문자 
        mov al, 0x0d
        int 0x10
    
        popa
        ret
    

    boot_sect_print_function_hex.asm

    16진수를 출력하는 기능을 가지고 있습니다. print_hex의 경우 caller에서 dx레지스터에 출력할 값을 넘겨줍니다. 이때 16진수의 마지막 문자를 가지고 와서 숫자일 경우 ASCII Code 값을 맞춰주기 위해 0x30만큼 더해주고, 알파벳인 경우 0x30을 더해준 후 7을 또다시 더해줍니다. 이는 9의 ASCII 값이 0x39이고 'A'의 값은 0x41이기 때문입니다. 출력할 문자열을 bx레지스터에 저장하고, 현재 문자열을 끝에서부터 처리하므로 해당 인덱스를 계산하고 계산된 위치에 값을 넘깁니다. 그런 다음 ror 연산을 통해 문자열을 한 칸씩 당기고 위 과정을 반복합니다.

    print_hex:
        pusha
    
        ; cx loop의 인덱스
        mov cx, 0
    
    hex_loop:
        cmp cx, 4
        je end
    
        ; dx에 입력 받음 
        mov ax, dx
        ; 마지막 문자만 남김
        and ax, 0x000f
        ; 0의 ASCII 값은 0x30, 0x30 더해야 함
        add al, 0x30
        ; 'A'의 ASCII 값은 0x41
        cmp al, 0x39
        jle step2
        ; 9 이상의 값보다 크면 7더해야 함
        add al, 7
    
    step2:
        ; 뒤에서 부터 채워나가기 때문
        mov bx, HEX_OUT+5
        ; 문자의 인덱스 계산
        sub bx, cx
        ; bx가 가리키는 곳에 al에 저장된 문자 넘김
        mov [bx], al
        ; ex 0x1234 -> 0x4123 (한칸씩 순환)
        ror dx, 4
    
        add cx, 1
        jmp hex_loop
    
    end
        ; boot_sect_print_function의 print함수 사용
        mov bx, HEX_OUT
        call print
    
        popa
        ret
    
    HEX_OUT:
        db '0x0000', 0

    boot_sect_main.asm

    main역할을 하는 코드입니다.

    [org 0x7c00]
    
    mov bx, HELLO
    call print
    
    call print_nl
    
    mov bx, BYE
    call print
    
    call print_nl
    
    mov dx, 0x12fe
    call print_hex
    
    call print_nl
    
    jmp $
    
    %include "boot_sect_print_function.asm"
    %include "boot_sect_print_function_hex.asm"
    
    HELLO:
        db 'Hello World',0x00
    
    BYE:
        bye db 'Good bye world',0x00
    
    times 510-($-$$) db 0
    dw 0xaa55

    실행 결과

    위 코드를 실행 bin파일로 컴파일하고, qemu로 실행시키면 다음과 같은 화면이 나옵니다. 저장된 문자열 'Hello World', 'Good bye world'와 0x12FE의 16진수 표기가 출력되는 것을 확인할 수 있습니다.

    실행 결과

     

    'OS > OS from Scratch' 카테고리의 다른 글

    [OS] 07. Boot Sector Disk  (0) 2021.06.20
    [OS] 06. Boot Sector Segmentation  (0) 2021.06.20
    [OS] 04. Boot Sector Stack  (0) 2021.06.20
    [OS] 03. Boot Sector Memory  (0) 2021.06.20
    [OS] 02. Boot Sector Print  (0) 2021.06.20
Designed by Tistory.