부트 로더를 테스트하기 위해 임시적인 OS 이미지를 만드는데, 부트 로더 코드를 기반으로 OS가 실행되었음을 표시하는 기능만 넣습니다.
가상 OS 이미지는 자신의 섹터 번호를 화면 위치에 대응시켜서 0 ~ 9까지 번호를 출력한다면 화면에 출력된 문자의 위치와 수를 확인하여 정상여부를 판단할 수 있습니다.
최종 FS64 OS 이미지가 수백 KB로 구성되기 때문에 가상 OS 이미지의 크기는 적어도 수백 KB 정도는 되어야 하므로 충분한 크기인 512KB(512B * 1024섹터) 크기로 정했습니다.
NASM 전처리기는 매크로(Macro), 조건(Condition), 반복(Loop) 구문을 지원하고, 변수 할당과 값 지정도 가능하기 때문에 이러한 구문을 잘 활용하면 숫자를 변경하는 것만으로 가상 OS 이미지의 크기를 변경할 수 있다는 점을 이용하여 1024섹터나 되는 코드를 작성합니다.
가상 OS 이미지는 거의 같은 코드가 반복되는 구조입니다.
첫 번째 섹터에 삽입할 코드를 구현하고, 이를 반복하여 나머지 섹터를 생성합니다.
01.Kernel32 디렉터리에 VirtualOS.asm 파일을 생성합니다.
VirtualOS.asm 파일은 가상 OS 소스 파일로 사용할 것입니다.
아래의 코드를 입력합니다.
부트 로더 코드와 동일한 방식으로 레지스터 초기화를 수행한 뒤 화면 2번째 라인의 가장 왼쪽 위치에 0을 출력합니다.
SECTORCOUNT라는 메모리 어드레스는 정상적으로 처리된 섹터의 수를 기록하고, 이를 사용해 화면에 출력될 좌표를 계산할 용도로 추가합니다.
이제 위의 코드에서 확장하여 1024섹터 중에 마지막 섹터를 제외한 1023섹터의 코드는 화면에 자신을 출력하는 코드 및 다음 섹터의 주소로 이동하는 코드를 반복합니다.
그리고 마지막 섹터는 자신을 출력하고 무한 루프를 수행하도록 하면 끝입니다.
NASM 어셈블러의 전처리문은 % 문자로 시작합니다.
NASM 어셈블러는 반복되는 구문을 위해 %rep ~ %endrep 이라는 전처리문을 제공하는데
times와 동일하게 반복 횟수와 반복할 대상을 입력하면 되고, %rep 과 %endrep 사이의 코드를 반복 횟수만큼 확장해줍니다.
변수 할당과 대입문은 %assign을 사용하고, 조건문은 %if ~ %elif ~ %else ~ %endif을 사용합니다.
TOTALSECTORCOUNT라는 상수를 1024로 정의하여 1024섹터의 OS 이미지가 생성되도록 구현합니다.
(equ 명령은 상수를 정의하는 명령입니다.)
→ %assign i 0
● i라는 변수를 지정하고 0으로 설정. i = 0과 동일
→ %rep TOTALSECTORCOUNT
● $endrep까지의 라인을 TOTALSECTORCOUNT번 반복하여 삽입
→ %assign i i+1
● i의 값을 1 증가, i = i + 1과 동일
→ %if i == TOTALSECTORCOUNT
● i의 값이 TOTALSECTORCOUNT와 같으면, 즉 마지막 섹터이면 아래의 라인을 삽입
→ %else
● 위의 %if 조건이 일치하지 않았을 때 아래의 라인을 삽입
→ %endif
● if 블록 종료
→ times ( 512 - ( $ - $$) % 512) db 0x00
● 각 섹터의 상위에 화면 출력 코드를 삽입하고 512byte 단위로 정렬하기 위해 남은 영역을 0으로 채움
→ %endrep
● rep 블록 종료
위의 코드는 NASM의 전처리기에 의해 확장될 시 1023섹터까지는 화면에 자신의 섹터 번호를 출력하고 다음 섹터로 이동하는 코드가 삽입되며
1024섹터는 자신의 섹터 번호를 출력하고 무한 루프를 수행하는 코드가 삽입됩니다.
이제 가상 OS 소스 코드를 이미지 파일로 생성합니다.
01.Kernel32 디렉터리 안에 makefile을 만들어서 아래의 내용을 입력해줍니다.
→ OS 이미지 통합과 QEMU 실행
부팅 이미지를 만드는 작업은 최상위 디렉터리에 있는 makefile이 담당하고 있습니다.
이미 생성되어 있는 FS64 OS 디렉터리의 makefile에 가상 OS에 관련된 부분만 추가하여 테스트 합니다.
부트 로더와 같은 방법으로 01.Kernel32 디렉터리에서 make를 수행하여 가상 OS 이미지를 빌드합니다.
그리고 부트 이미지를 복사해서 부팅 이미지를 만드는 기존 방식을 수정하여 부트 로더와 가상 OS 이미지를 하나의 파일로 합치도록 수정합니다.
cat을 사용하면 'cat A B C > D'와 같은 방식으로 A, B, C 파일을 하나로 합쳐 D 파일로 만들 수 있습니다.
아래의 내용과 같이 수정합니다.
이제 자신이 사용하는 IDE(ex. eclipse)에서 프로젝트를 빌드해주거나
터미널에서 FS64 OS 디렉터리로 이동하여 make 명령을 입력하여 빌드해줍니다.
그리고 QEMU를 실행해주면 아래와 같은 결과가 뜰 것입니다.
추후 데스트를 더 해보고 싶다면 부트 로더와 가상 OS의 TOTALSECTORCOUNT의 값을 1과 1152 사이의 값으로 변경한 후 같은 방법으로 테스트하면 됩니다.
섹터의 최댓값이 1152인 이유는 OS 이미지가 로딩되는 주소가 0x10000이고 상위 0xA0000 이후 영역은 비디오 메모리로 사용되기 때문입니다.
그리하여 OS를 로딩할 수 있는 전체 크기는 0x90000byte(0xA0000 - 0x10000, 576Kbyte)가 되며, 섹터가 512byte 크기이므로 최대 1152섹터입니다.
참고)
리얼 모드에서 BIOS 서비스를 최대한 활용하려고 하니 OS 이미지가 최대 1152섹터라는 제약사항이 생겼는데, BIOS 제조사에 따라서 비디오 메모리 주소의 앞쪽을 다른 용도로 사용할 수 있기에 실제로는 더 작을 수 있습니다.
그래서 OS 이미지가 너무 크다면 OS 이미지를 압축하거나, BIOS 서비스로 OS의 일부만 메모리에 로딩하고 나머지 부분은 보호 모드로 전환한 후 디바이스에 직접 접근하는 방식으로 해결해야 합니다.
FS64 OS의 최종 크기는 응용프로그램을 포함하여 570KB 정도이므로 BIOS 서비스만으로도 충분합니다.
'시작하지 말았어야 했던 것 > 64비트 멀티코어 OS' 카테고리의 다른 글
64비트 멀티코어 OS[5] - 2. 보호 모드로 전환과 보호 모드용 커널 이미지 빌드와 가상 OS 이미지 교체 (0) | 2021.03.09 |
---|---|
64비트 멀티코어 OS[5] - 1. 세그먼트 디스크립터 생성과 GDT 정보 생성 (0) | 2021.03.08 |
64비트 멀티코어 OS[4] - 2. 보호 모드에서 사용되는 세 가지 함수 호출 규약과 최종 부트 로더 코드 (0) | 2021.03.03 |
64비트 멀티코어 OS[4] - 1. 플로피 디스크에서 OS 이미지를 로딩 (0) | 2021.03.03 |
64비트 멀티코어 OS[3] - 4. 화면 버퍼와 화면 제어 (0) | 2021.02.18 |