'NSG(Nefus Study Group)/Assignment'에 해당되는 글 5건

  1. 2008.11.04 BPB, File System 분석 (FAT 12)
  2. 2008.10.29 NEFUS Study Group Assignment 0x4
  3. 2008.10.29 NEFUS Study Group Assignment 0x3
  4. 2008.10.28 NEFUS Study Group Assignment 0x2 1
  5. 2008.10.28 NEFUS Study Group Assignment 0x1 4

File System 분석


db 0xEB 0x58 0x90

; jmp 0x58

; nop

BS_jmpBoot / 오프셋 0바이트 / 크기 3바이트 / 0xeb는 오프셋 1바이트(1바이트 채워주기 위해 0x90 nop(no operation)을 사용한다. 0xe9는 오프셋 2바이트


db 0x57 0x49 0x4E 0x49 0x4D 0x41 0x47 0x45

아스키 코드 값이 들어감

0x57 = W 0x49 = I 0x4E = N 0x49 = I 0x4D = M 0x41 = A 0x47 = G 0x45 = E

BS_OEMName / 오프셋 3바이트 / 크기 8바이트 / WINIMAGE가 들어가있다. 이 부분에 호환성 문제로 보통 MSWIN4.1을 넣는다.


db 0x00 0x02

<------------ Little-endian

BPB_BytsPerSec / 오프셋 11바이트 / 크기 2 바이트 / 섹터당 바이트수 /512, 1024, 2048, 4096을 넣을 수 있다. 호환성 문제로 512를 사용한다.


db 0x01

BPB_SecPerClus / 오프셋 13바이트 / 크기 1바이트 / 클러스터당 섹터수 / 이부분은 0보다 커야하고 1,2,4,8,16,32,64,128이 허용된다.

db 0x01 0x00
BPB_RsvdSecCnt /
오프셋 14바이트 / 크기 2바이트 / reserved된 섹터수 / 이 필드는 0이되면안되는데 FAT12, FAT16에서 1이여야 한다. MBR이 첫번째 섹터를 차지하기 때문에 reserved 해준다.

db 0x02

BPB_NumFATs / 오프셋 16바이트 / 크기 1바이트 / FAT Entry개수. FAT File System 에서 이 필드는 항상 2를 가지고 있는데 FAT Entry가 날아가면 나머지 한개를 참조한다.

db 0xE0 0x00

00E0 = 224

BPB_R ootEntCnt / 오프셋 17바이트 / 크기 2바이트 / 루트 디렉토리의 32바이트짜리의 디렉토리 요소 항목의 수이다.


Db 0x40 db0x0b

BPB_TotSec16 / 오프셋 19바이트 / 크기 2바이트 / 볼륨의 모든 4개 부분에 있는 총 16비트짜리인섹터의 개수이다.



db 0xf0

BPB_Media / 오프셋 21바이트 / 크기 1바이트 / 0xF8은 고정된 매체의 표준 값이다. Removable media0xF0이 자주 쓰임. 여기서 fat12 (floppy disk) 파일 시스템이기 때문에 0xf0이다.


Db 0x09 0x00

BPB_FATSz16 / 오프셋 22바이트 / 크기 2바이트 / 한개의 FAT에서 차지하고 있는 FAT12, FAT1616비트 개수.


Db 0x12 0x00

BPB_SecPerTrk / 오프셋 22바이트 / 크기 2바이트 / 인터럽트13번을 위한 트랙당 섹터수.


Db 0x02 0x00

BPB_NumHeads / 오프셋 26바이트 / 크기 2바이트 / 인터럽트 13번을 위한 헤드의 수


db 0x00 0x00 0x00 0x00

BPB_HiddSec / 오프셋 28바이트 / 크기 4바이트 / 숨겨진 섹터의 개수이다. 이 섹터들은 파티션이 없으면 항상 0이어야한다.


Db 0x00 0x00 0x00 0x00

BPB_TotSec32 / 오프셋 32 바이트 / 크기 4바이트 볼륨에 있는 섹터의 총32비트의 개수


db 0x0

BS_DrvNum / 오프셋 36바이트 / 크기 1바이트 / 인터럽트 13번의 드라이브 번호이다. 플로피 디스크일경우 0x00, 하드디스크일 경우 0x80으로 인터럽트13번에서 세팅한다.


Db 0x0

BS_Reserved1 / 오프셋 37바이트 / 크기 1바이트 / Reserved해놓는다. Windows NT 에서 사용.

FAT 형식은 반드시 0으로 세팅되야함


db 0x29

BS_BootSig / 오프셋 38바이트 / 크기 1바이트 / 확장된 부트 표시이다.


Db 0x19 0x34 0x10 0x25

BS_VolID / 오프셋 39바이트 / 크기 4바이트 / 볼륨 시리얼 넘버이다.


Db 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20

BS_VolLab / 오프셋 43바이트 / 크기 1바이트 / 루트디렉토리 안에 11바이트의 볼륨라벨이 기록된다.


Db 0x46 0x41 0x54 0x31 0x32 0x20 0x20 0x20

BS_FilSysType / 오프셋 54바이트 / 크기 8바이트 / “FAT12 “ 여기에 기록된다고 해도 BPB에 영향을 주지 못하고 단지 정보만 알려주는 문자열이다.


"GOODJOB "DIR_NAME(짧은 이름)이다.

0x10DIR_Attr를 말한다.(0x10 디렉토리임)

그 후 1바이트는 DIR_NTRes로서, Window NT가 아니므로 0이다.

그 후 1바이트는 1/10초 단위의 파일 생성 시각으로, 0으로 되어있다.

그 후 2바이트는 파일이 생성된 시간으로, 0으로 되어있다.

그 후 2바이트는 파일이 생성된 날짜로, 0으로 되어있다.

그 후 2바이트는 최근에 접근한 날자로, 0으로 되어있다.

그 후 2바이트는 엔트리의 첫번째 클러스터 번호이다. FAT12에선 항상 0이다.

그 후 2바이트는 최근에 쓰여진 시간으로, 0xA399, 41881로 되어있다.

그 후 2바이트는 최근에 쓰여진 날짜로, 0x395F, 14687로 되어있다.

그 후 2바이트는 엔트리의 첫번째 클러스터 번호로, 로우 0x2이다.

으 후 4바이트는 FileSize, 0으로 되어있다.

20

그 다음 있는 파일은

"ABC TXT"DIR_NAME(짧은 이름)이다.

0x10DIR_Attr를 말한다.(0x0 파일임)

그 후 1바이트는 DIR_NTRes로서, Window NT를 위해서 0x18이다.

그 후 1바이트는 1/10초 단위의 파일 생성 시각으로, 0x8E65, 36453으로 되어있다.

그 후 2바이트는 파일이 생성된 시간으로, 0x5FAC, 24492로 되어있다.

그 후 2바이트는 파일이 생성된 날짜로, 0x39, 57로 되어있다.

그 후 2바이트는 최근에 접근한 날자로, 0으로 되어있다.

그 후 2바이트는 엔트리의 첫번째 클러스터 번호이다. FAT12에선 항상 0이다.

그 후 2바이트는 최근에 쓰여진 시간으로, 0xA399, 41881로 되어있다.

그 후 2바이트는 최근에 쓰여진 날짜로, 0x395F, 14687로 되어있다.

그 후 2바이트는 엔트리의 첫번째 클러스터 번호로, 로우 0x4이다.

으 후 4바이트는 FileSize, 16byte으로 되어있다.


(Reference)

FAT(File Allocation Table) 영문 문서 - pdf. MS에서 제공한 FAT 문서. 원제 "General Overview of On-Disk Format".

Posted by Triton
,

바이오스 인터럽트를 사용하여, 다음 섹터를 읽어 제어권 넘기기.



주의할 점: 불러들일 프로그램의 크기는 1024 Bytes(2 sectors) 이상이며, 디스크에서 읽어 들일때, 읽어들이는 과정을 표시할 수 있도록 함.


read :
   mov ax, 0x1000
   mov es, ax ;code segment
   mov bx, 0 ; data segment
   ES:BX ->Data Buffer

    mov ah, 2
   mov al, 2 ; number of sectors to read (must be nonzero)
   mov ch, 0 ; low eight bits of cylinder number
   mov cl, 2 ; sector number 1-63 (bits 0 - 5)
   mov dh, 0 ; head number
   mov dl, 0 ; drive number (bit 7 set for hard disk)
   int 0x13
  
   jc read    ; error 생기면 read 로 jump
  
   jmp 0x1000:0000

Return:
CF set on error
if AH = 11h (corrected ECC error), AL = burst length
CF clear if successful
AH = status
AL = number of sectors transferred (only valid if CF set for some BIOSes)

Posted by Triton
,

32bit Protected Mode에 진입하기. (A20 라인을 활성화한 것과, 하지 않은 것을 비교하여 제출)

주의할 점: 진입하여 문자열을 출력할 것. (정상적으로 부팅 됬다는 것을 보여주면 됨), 32bit 진입은 Kernel(외부 2차적 프로그램)에서 수행할 것.

 enableA20 :   
    mov ax, 0x2401  ;;disable : mov ax, 0x2400
    int 0x15
    jc enableA20
   
getstatus :
    mov ax, 0x2402
    int 0x15
   
    cmp al, 1
    je Success
    jne Failed
   
Success :
    mov esi, Successs
    call prints
    jmp endstatus
Failed :
    mov esi, Fail
    call prints
    jmp endstatus
   
endstatus :

인터럽트를 사용하여 A20라인을 Enable 하고 문자열 출력하기.
A20 라인 상태를 인터럽트를 사용하여 얻어와서 Enable,Disable일 경우 해당 메세지 출력

Posted by Triton
,

어셈블리로 puts 만들기

1. 주의할 점: Carrage Return, Line Feed, Null Character를 인식하며, 바이오스 인터럽트를 사용하지 않은채 구연할 것.

2. 제출 기한은 포스팅일로부터 3일.

3. 제출은 트랙백으로 제출할 것.

[org 0h]
[bits 16]

jmp 0x7c0:start
strA db 'HELLO WORLD',10,10,10,13,'ASDF',10,13,'A',0
start :
    xor esi, esi
    mov ax, cs
    mov ds, ax
    mov ax, 0xb800
    mov es, ax
    xor di, di
    push di
    mov si, strA
    call puts
   
    jmp $



linef :
    mov ax, di
    add di, 160
    inc si
    jmp print_loop
   
carr :
    xor dx, dx
    mov ax, di
    mov bx, 160
    div bx
    mul bx
    mov di, ax
    inc si
    jmp print_loop
   
puts :

    pop di
    xor di, di
    xor dx, dx
print_loop :
    mov dl, [si]
    cmp dl, 10 ;linefeed
    je linef
    cmp dl, 13 ;carriage return
    je carr
    cmp dl, 0
    je endputs
    mov byte[es:di], dl
    inc di
    mov byte[es:di], 0x06
    inc di
    inc si
    jmp print_loop
endputs :
    push di
    ret
※ 2바이트 이상 div를 하게 되면 dx:ax 값을 가지고 나누기를 하여 몫은 ax에 나머지는 dx에 저장된다.

Posted by Triton
,



32bit Protected Mode로 진입하여, 문자열 찍기.


32비트 키는 순간 재부팅이 되어서 무엇이 문제인지 모르고 있다가 32비트에선 바이오스 인터럽트가 먹히지 않는 다는 것에 코드를 다시 수정하고 어셈 파일을 두개로 나눠서 작성하였다.
0x1000:0000으로 Far 점프를 하기 위해 gdt 코드 세그먼트, 데이타 세그먼트의 베이스 어드레스를 dw 0x0000 db 0x01로 하여 베이스를 0x00010000로 맞춰주었다.
;;;;;;;;;;;;;;;;;;;;;;;;;build.sh;;;;;;;;;;;;;;;;;;;;;;;;;;
rm -f boot kernel image.img
nasm boot.asm -o boot
nasm kernel.asm -o kernel
dd if=boot of=image.img seek=0
dd if=kernel of=image.img seek=1
dd if=boot of=image.img seek=2880
;;;;;;;;;;;;;;;;;;;;;;;end build;;;;;;;;;;;;;;;;;;;;;;;;;;;
build.sh를 사용하여 boot.asm과 kernel.asm의 바이너리 파일을 만들고 그파일을 image.img파일로 맞춰주었다. if=FILE  (read from FILE instead of stdin)
of=FILE (write to FILE instead of stdout)
seek=BLOCKS (skip BLOCKS obs-sized blocks at start of output)


저번에 다른 블로그에서 본 disk 섹터를 메모리에 읽는 인터럽트 마지막에 jmp 0x1000:0000이 왜 써져있나 싶어서 이것을 지우고 사용하였는데 파일을 두개로 하기때문에 far jump를 하여 세그먼트가 조정되어서 사용한다는 것을 알게 되었다.


Posted by Triton
,