Read Sector From Floppy

Programming 2008/07/17 22:53 귀차니스트

  음 일단 진행 됬던건.. BIOS가 처음 POST 과정을 끝내고 BIOS에서 지정된 순서로 부팅 디스크를 검색하여 Magic Sign에 해당하는 첫 번째 디스크의 첫 번째 섹터를 7C00h 번지로 올려준다는 것을 전제로 간단한 Hellow World 출력까지 진행했었기에, 어제 자기전까지 섹터 읽는 것을 구현을 해봤죠. 뭐 그다지 복잡한 것은 아니지만 괜히 삽질하고 있었더군요.

Sector.asm (Language : asm)
  1. [org 7C00h]
  2. EntryPoint:
  3.     mov ax, 0000h
  4.     mov es, ax
  5.     mov ax, 0201h
  6.     mov cx, 0002h
  7.     mov dx, 0000h
  8.     mov bx, 7E00h
  9.     int 13h
  10.     jmp PrintPoint
  11. times 510-($-$$)    db 0
  12.     dw 0AA55h
  13. %macro PRINT 1
  14.     pop dx
  15.     mov di, %1
  16.     mov ah, 0Eh
  17.     xor bx, bx
  18.     mov cx, 14
  19. printloop:
  20.     mov al, byte[di]
  21.     int 10h
  22.     inc di
  23.     loop printloop
  24. %endmacro
  25. PrintPoint:
  26.     mov ax, 1301h
  27.     mov bx, 0007h
  28.     mov cx, 21
  29.     mov dh, 0
  30.     mov dl, 0
  31.     mov bp, MSGLOAD
  32.     int 10h
  33.     ;PRINT MSGLOAD
  34. Loading:
  35.     jmp Loading
  36. MSGLOAD equ $
  37.     db "Message from Sector 2"

  일단 예전과는 다르게 PrintPoint로 EntryPoint를 변경한 뒤, 512바이트 뒤로 명령어 데이터를 옮겼습니다. 왜 이렇게 했냐하면 플로피디스크에서야 잘 모르겠지만 나중에 하드디스크 MBR에 이미지를 Write하여 부팅을 하려고 할 때, 파티션 데이터에 대한 처리를 쉽게 허용하기 위해서 였죠.
  기본적으로 한 섹터는 512바이트이기 때문에, 첫 번째 512바이트는 7C00h번지로 올라가게 되고, 512 바이트 뒤의 데이터는 플로피 같은 디스크 매체에 그대로 남아있게 됩니다. 별도의 로딩과정이 존재하지 않게 되죠. 하지만 512바이트로는 뭐 콩을 구워먹을래도 할 수 있는 일이 없기 때문에 디스크 매체에서 데이터를 읽어들여야 합니다.
  그래서 INT13H의 02H인터럽트를 통하여 2번째 섹터를 읽어 7C00h + 512바이트 주소인 7E00h번지로 로딩을 하게 설정합니다. 기본적인 인자값은 위키피디아에 존재하므로 그 부분을 감안하여 본 뒤 작성하시면 됩니다. 맨 처음 [ORG 7C00h]라는 Directive로 해당 명령어의 시작 지점이 7C00h라는 것을 알려주었기 때문에 생성되는 Label 및 변수에 대해서 주소값은 7C00h를 상대값으로 가지게 됩니다.
  결국 컨트롤이 쉽게 된달까요. 뭐 어찌되었던 512바이트 이후에 예전에 작성했던 코드를 밀어넣고 INT13H를 호출한 후 해당 메모리 주소로 점프를 합니다. 그럼 섹터가 로딩되기 전엔 쓰레기 값이 들어있었을 메모리에 제대로 된 명령어들이 들어있게 되고, 출력 명령어를 잘 수행하게 되죠. 다만 여기서 중요한 것은 02H에 해당하는 Sector Address는 1이 MBR이고 2가 두 번째 섹터더군요. 너무나 인덱스에서 0에 익숙해져 있는 관계로 1을 적었다가 왜 안되지 했었습니다.

Trash.asm (Language : asm)
  1. [org 7C00h]
  2. EntryPoint:
  3.     mov ax, 0000h
  4.     mov ds, ax
  5.     mov si, DAPStruture
  6.     mov ah, 42h
  7.     mov dl, 00h
  8.     int 13h
  9.     jmp PrintPoint
  10. DAPStruture:
  11.     db 10h      ;sizeof(DAP)
  12.     db 00h      ;zero
  13.     db 01h      ;read sector count
  14.     db 00h      ;zero
  15.     dw 0000h        ;segment
  16.     dw 7E00h        ;offset
  17.     dq 0000000000000001h    ;number of sector
  18. times 510-($-$$)    db 0
  19.     dw 0AA55h
  20. %macro PRINT 1
  21.     pop dx
  22.     mov di, %1
  23.     mov ah, 0Eh
  24.     xor bx, bx
  25.     mov cx, 14
  26. printloop:
  27.     mov al, byte[di]
  28.     int 10h
  29.     inc di
  30.     loop printloop
  31. %endmacro
  32. PrintPoint:
  33.     mov ax, 1301h
  34.     mov bx, 0007h
  35.     mov cx, 21
  36.     mov dh, 0
  37.     mov dl, 0
  38.     mov bp, MSGLOAD
  39.     int 10h
  40.     ;PRINT MSGLOAD
  41. Loading:
  42.     jmp Loading
  43. MSGLOAD equ $
  44.     db "Message from Sector 2"

  별개로 이 것은 위키피디아를 읽다가 42H에 해당하는 기능이 읽어보니 훨씬 좋은 기능을 지원하길래 혹시나 하고 작성해봤던 코드입니다. 액세스할 수 있는 주소가 엄청 크기 때문에 원하는 곳을 모두 액세스 할 수 있었는데, 어제 테스트해본 결과론 죽어라 해도 안되더군요. 결국 오늘 까마구 횽님과 대화하다가 다른 문서에서도 플로피에 대한 언급이 없었다고, 이 것은 아무래도 하드디스크에서만 지원하는 것 같다는 결론을 얻게 되었습니다.
  그럼 오늘은 시간이 될 지는 모르겠습니다만 GDT, IDT, LDT에 대해서 자료를 보고 한 번 설정을 해봐야 겠군요^^. 뭐 어떻게 될지는 잘 모르겠지만 잘 되리라 믿습니다.

크리에이티브 커먼즈 라이센스
Creative Commons License
2008/07/17 22:53 2008/07/17 22:53
TAG

트랙백 주소 :: http://www.filewiki.net/tc/trackback/93

댓글을 달아 주세요