어제에 이어서 helloos.nas내용을 살펴보는것부터 시작합니다.

떡하니 갑자기 새로운 helloos.nas를 주는군요.. 그러면서.. 뭐 같은거라 하니..저도 뭐 ^^;;
그리고는 여기서 나오는 어셈블 명령어를 설명해 줍니다.

여기서 사용하는 어셈블러는 nask라는 것으로 OS제작기 No1에 올려놨답니다. ^-^;

; hello-os
; TAB=4

  ORG  0x7c00   ; 이 프로그램이 어디에 read되는가

; 이하는 표준적인 FAT12 포맷 플로피 디스크를 위한 기술

  JMP  entry
  DB  0x90
  DB  "HELLOIPL"            ; boot sector이름을 자유롭게 써도 좋다(8바이트)
  DW  512                       ; 1섹터 크기(512로 해야 함)
  DB  1                           ; 클러스터 크기(1섹터로 해야 함)
  DW  1                          ; FAT가 어디에서 시작될까(보통 1섹터째부터)
  DB  2                           ; FAT 개수(2로 해야 함)
  DW  224                       ; 루트 디렉토리 영역의 크기(보통 224엔트리로 해야 한다)
  DW  2880                      ; 드라이브 크기(2880섹터로 해야 함)
  DB  0xf0                       ; 미디어 타입(0xf0로 해야 함)
  DW  9                          ; FAT영역 길이(9섹터로 해야 함)
  DW  18                        ; 1트럭에 몇 개의 섹터가 있을까(18로 해야 함)
  DW  2                         ; 헤드 수(2로 해야 함)
  DD  0                          ; 파티션을 사용하지 않기 때문에 여기는 반드시 0
  DD  2880                     ; 드라이브 크기를 한번 더 write
  DB  0,0,0x29                ; 잘 모르지만 이 값으로 해 두면 좋은 것 같다
  DD  0xffffffff                  ; 아마, 볼륨 시리얼 번호
  DB  "HELLO-OS   "      ; 디스크 이름(11바이트)
  DB  "FAT12   "             ; 포맷 이름(8바이트)
  RESB 18                     ; 우선 18바이트를 비어 둔다

; 프로그램 본체

entry:
  MOV  AX, 0                 ; 레지스터 초기화
  MOV  SS,AX
  MOV  SP,0x7c00
  MOV  DS,AX
  MOV  ES,AX

  MOV  SI,msg
putloop:
  MOV  AL,[SI]
  ADD  SI, 1                     ; SI에 1을 더한다
  CMP  AL,0
  JE  fin
  MOV  AH, 0x0e              ; 한 글자 표시 Function
  MOV  BX, 15                  ; 칼라 코드
  INT  0x10                       ; 비디오 BIOS 호출
  JMP  putloop
fin:
  HLT                               ; 무엇인가 있을 때까지 CPU를 정지시킨다
  JMP  fin                         ; Endless Loop

msg:
  DB  0x0a, 0x0a                ; 개행을 2개
  DB  "hello, world"
  DB  0x0a                        ; 개행
  DB  0

  RESB 0x7dfe-$                 ; 0x7dfe까지를 0x00로 채우는 명령

  DB  0x55, 0xaa

; 이하는 boot sector이외의 부분을 기술

  DB  0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
  RESB 4600
  DB  0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
  RESB 1469432


뭐.. 오늘은 어셈블러 명령어에 대해서 많이 배워보는 시간일듯 하다.ㅎ
차근차근 하나씩 해보자.ㅎ

ORG : 'origin' 기계어가 실행시에 PC의 메모리내 어디에 로딩되는지를 nask에 가르쳐주기 위한 명령 (이로 인하여 $표시의 의미가 바뀌게 된다는데, 출력파일로부터의 번지수가 아니라 ORG에 지정된 주소로부터 몇번째 번지인지를 나타내게 됨)

JMP : 'jump' C언어로 따지면 goto ~~ 긴말이 필요 없다.ㅎ 그냥 지정된 분기로 이동한다.

레이블의 선언 ( ex) entry: ) : <-요 표시를 하면 바로 레이블의 선언이 된다. JMP명령이 이동할 곳을 지정할때 등에 사용된다.

MOV : 'move' 간단하게 이동 예를들어 MOV AX,0 은 AX = 0 과 같은 의미이다. C언어의 대입연산자와 같다고 보면 됨. (뭐 추가적으로 설명이 있자면 MOV SS,AX 라고한다면 SS = AX; 이지만 AX의 데이터가 지워지는 일은 없다. copy에 가까운 행동이다...ㅡ.ㅡ;; 근데 왜 MOVE?뭐 나도 모르지..ㅜㅜ)

CPU 내부의 대표적인 레지스터 8개
AX ........ 어큐뮬레이터(accumulator: 누적 연산기라는 의미)
CX ........ 카운터(counter: 수를 세는 기계라는 의미)
DX ........ 데이터(data: 데이터라는 의미)
BX ........ 베이스(base: 기초, 기점이라는 의미)
SP ........ 스택 포인터(stack pointer: 스택용 포인터)
BP ........ 베이스 포인터(base pointer: 베이스 포인터)
SI  ........ 소스 인덱스(source index: 읽기 인덱스)
DI  ........ 데스티네이션 인덱스(destination index: 쓰기 인덱스)
:: 이것들은 모두 16비트 레지스터로 뭐 읽을땐 이름보다도 에이엑스 에스아이레지스터 등 표기 그대로 읽고 있단다.;;
:: 또한 위의 나열은 기계어에 따라 레지스터 번호순으로 나열한것이다.

CPU 내부의 8bit 레지스터 8개
AL ........ 어큐뮬레이터 로우(low:낮다)
CL ........ 카운터 로우
DL ........ 데이터 로우
BL ........ 베이스 로우
AH ........ 어큐뮬레이터 하이(high:높다)
CH ........ 카운터 하이
DH ........ 데이터 하이
BH ........ 베이스 하이
:: AX = AH + AL 
        = AH(8~15bit) + AL(0~7bit)
그런고로 CPU는 총 아무리 해봐야 16바이트 밖에 기억을 하지 못한다.!! ㅡ.ㅡ;; 좀충격적이다. 위의 CPU구조는 16BIT 컴퓨터 이다. 허나 요샌 32bit, 64bit이다. 요건 요거 나름대로 예를 들어 32bit같은 경우의 레지스터리는 
EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI
요렇게 진행이 된다고 한다. E는 extend(확장)의 의미...ㅎ뭐 16bit로도 지금은 벅차다 ^^;;

세그먼트 레지스터
ES ........ 엑스트라 세그먼트(extra segment:덤 세그먼트)
CS ........ 코드 세그먼트(code segment)
SS ........ 스택 세그먼트(stack segment)
DS ........ 데이터 세그먼트(data segment)
FS ........ 명칭 없음(덤 세그먼트 2번째)
GS ........ 명칭 없음(덤 세그먼트 3번째)
:: 16bit 레지스터 이다. 이 설명은....... 아쉽지만 내일 한다고 한다.ㅡ.ㅡ;;;쭈욱~~ 설명해주면 안되나?;;
다시 저위의 helloos.nas의 어셈블로 짜여진 소스를 보자면

MOV SI,msg
:: SI=msg 라는 표현이 맞는거지만 msg라는것은 레이블이므로 레이블에 해당되는 주소부분은 SI에 넣으라는 표현으로 생각하면 된다.

MOV AL,[SI]
:: 값자기 명령어 설명을 하다가 이부분에서 메모리 설명이 나오게 되네요 저도 이걸 어찌정리해야할지 난감하군요.ㅜ
   뭐 그래도 설명을 쭈욱 해보자면 이제껏 16bit CPU는 총 16바이트밖에 저장을 못한다는 아주 불우한 사실을 알게되었습니다. 네 바로 그겁니다. CPU는 처리장치 아니 처리밖에 못하게끔 만들어진 것이지요 그럼 그 많은 크기의 데이터들은 어떻게 하느냐 바로 RAM에 저장이 되어서 CPU가 1명령어씩 처리해주는것이지요 뭐 그렇다는 겁니다. 메모리를 소개해야 저 []가 설명이 되네요 .^^;
:: MOV AL, BYTE [SI] 와 위의 표현은 같은 표현으로써 AL에 메모리의  SI번지에 해당하는 데이터를 옮겨라 입니다.ㅎ 이부분이 중요하죠 되지꼬리 별표 땡땡 ㅎㅎ BYTE와 같은 표현으로는 WORD, DWORD라고 있습니다. BYTE가 8bit WORD 16bit DWORD 32bit입니다.ㅎ
:: MOV WORD[678], 123 이라는 명령구문에 대해 잠깐 살펴보자면 메모리의 678번지와 679번지에 걸쳐서 123이라는 데이터를 넣어라 입니다만 여기서 단한가지 주의하고 놀라운 사실이 678번지에 123에 해당하는 01111011의 데이터가 들어가고 0에 해당되는 00000000의 데이터가 679번지에 들어가 진다는 것이지요 이것은 CPU설계부터가 그런것이라 무조건이라고 하니 어쩌겠습니까 잘 알아둘수 밖에 책의 그림의 설명이 너무 자세하고 분명하게 나와서 ㅎ 그대로 붙여보아요.ㅎ

 


ADD : 더하기

CMP : 'compare' 비교하라 ( ex) CMP AL,0 )
JE : 'jump if equal' CMP명령시 두 값이 같을경우 실행 ( AL == 0 일 경우 실행하라는 의미)

INT : 'interrupt' 방해하다. 자세한 설명은 다음기회에...ㅡ.ㅜ;
BIOS(Basic input output system)
OS제작자가 자주 사용할 것 같은 프로그램을 PC제조사가 미리 준비해둔 매우 고마운 물건 !?!!;; 이라고 소개가 되어있네요 처음 알았읍니다. 요런 용도일줄은..ㅋㅋㅋ

INT 뒤의 숫자를 적게 되는데 이를 통하여 BIOS내부 함수를 호출한다고 합니다.
뭐 자세한 내용은 AT-BIOS라는 글 참조해주세요 ^-^;;

HLT : 'halt' CPU를 정지시킨다는 의미랍니다.

아래는 위의 어셈블리어로 작성된 소스의 내용을 C언어식으로 다시 써본것입니다. 역시 C가 이해가 쉽네요.ㅎ;;;;
 entry:
    AX = 0;
    SS = AX;
    SP = 0x7c00;
    DS = AX;
    EX = AX;
    SI = msg;
putloop:
    AL  = BYTE [SI];
    SI = SI + 1;
    if( AL == 0 ) { goto fin; }
    AH = 0x0e;
    BX = 15;
    INT 0x10;
    goto putloop;
fin:
    HLT;
    goto fin;

자.. 여기까지하면 어셈블리어에 대한 설명과 우리가 만들어보았던 간단한 Hello OS도 살펴본 셈이 된다. CPU의 내부구조와 BIOS RAM의 관계까지 알게되었다.

여기서 한가지의 포인트가 존재하는데 바로 ORG의 번지이다.
고정으로 지정되어있는 번지.. 왜 거기서부터 시작되어야 하는가를 설명한다면
0x00007c00 ~ 0x00007dff : 부트섹터가 읽혀지는 어드레스
부트섹터 따로 어떻게 설명해야 좋을지 모르겠지만 간단하게 컴퓨터가 켜지자 마자 건드는 곳! 이라고 하면 되겠다. 내가 만들 OS의 메모리의 시작주소들을 심어놓을곳? 이라고 이해하면 되려나?어떻게 이해해야 할지는 모르겠지만 간단하게 부트섹터에 대해 저자는 이렇게 말하고 있다.

[ 디스크 이미지 전체를 nask로 만드는 것이 아니고, nask로는 일단 512바이트의 부트섹터만 만들고 나머지는 디스크 이미지 관리툴로 만든다. ] 라구... 뭐 부트섹터가 시작이라는 것과 거기에 모든 프로그램을 심는 것이 아니라 시작할 프로그램의 주소 번지를 심어두면 된다!?라는거겠지 ^^;;;

자 이렇게 어셈블리어로 프로그램을 짰다면 당당히 테스트 해봐야 할것이다.
헌데 복잡하게 어셈블 파일을 어셈블러로 컴파일하고 컴파일된 파일을 img파일로 만들고 이렇게 두번의 과정을 거친후 플로피 디스켓에 담아 테스트를 해야하는 것이다.;;;ㅡ.ㅡ;;

이 복잡한 과정을 쉽게 해결하기위한것이 바로 Makefile의 도입!!!
 #파일 생성 규칙

ipl.bin : ipl.nas Makefile
    ../z_tools/nask.exe ipl.nas ipl.bin ipl.lst

helloos.img : ipl.bin Makefile
    ../z_tools/edimg.exe imgin:../z_tools/fdimg0at.tek/wbinimg src:ipl.bin len:512 from:0 to:0 imgout:helloos.img

우선 저 위의 내용을 소개 하기전에 저자가 사용하는 z_tools에 대해 설명하고자 한다. 간단하게 nask나 gcc, make 등의 툴을 모아놓은것이다. 가상머신 qemu까지 있으므로 위의 저대로 실행을 한다면 바로 플로피디스켓을 이용한 VMware방식을 사용하지 않더라도 에뮬레이터로 돌려볼수 있는것이다.

 
그럼 다시 본문으로 돌아가서
#은 Makefile에서 주석과 같은 역할.
ipl.bin : ipl.nas Makefile
:: ipl.bin을 만들고 싶으면 먼저 ipl.nas 라는 파일과 Makefile이라는 파일이 갖추어져있는지 확인하시오. 갖추어져있다면 자동으로 실행됩니다.

뭐 이런 Makefile을 통해 여러가지 배치파일들을 간소화하고 명령어들을 묶어버리는 것이지요 ^^: 요부분은 깊게 다루지 않도록 하겠습니다.ㅎ

오늘은 어셈블러와 간단한 Makefile을 알아보는것으로 마치게 되네요 ^^! 이렇게해서 OS!! 되는거니? 그런거니? ㅎㅎㅎ;;

 
 

+ Recent posts