카테고리 없음
VBR Assembly Code 분석
좋은날
2014. 6. 3. 10:12
[출처 : http://wharak.egloos.com/viewer/402279]
참조 : http://thestarman.pcministry.com/asm/mbr/W7VBR.htm
하드디스크의 부트섹터를 HxD라는 툴로 살펴본 그림이다.
의미있는곳을 색깔로 표시해보았는데 역시 제일 마지막 워드에 매직넘버(55aa)가 보인다.
---------------------------------------------------------------
오프셋 바이트 쓰인값 의미
---------------------------------------------------------------
00 3 EB 52 90 short jump 52h + nop
jump 명령 2바이트 + 오프셋 52h = 54h 번지로 점프
03 8 4E 54 46 53 NTFS
20 20 20 20 공백네개
------------------------------------------
BPB(Bios Parameter Block)의 시작
------------------------------------------
0B 2 00 02 섹터의 크기 ( 0x200 : 512 바이트)
0D 1 08 클러스터당 섹터수 ( 08 x 512 = 4KiB)
0E 1 00 mbr코드에서 부팅디스크의 id를 써넣는다
80h(첫번째하드), 81h(두번째하드)
0F 2 00 00 부트섹터코드에서 20h가 들어가며 세그먼트증가값으로 쓰임
11 4 00 00 00 00 섹터지정 인텍스값으로 쓰임
15 1 F8 Media Descriptor ID(Fixed Disk)
16 2 00 00 1섹터를 몇번 읽을것인가를 나타내는데 쓰임
18 2 3F 00 트랙당 섹터수 ( 3Fh : 63개)
1A 2 FF 00 헤드의 갯수(FFh : 255개)
1C 4 00 08 00 00 예약된 섹터의 갯수 (800h : 2048개)
물리섹터번호 800h부터 논리섹터가 시작된다.
즉 800h섹터가 부트섹터가 된다
20 4 00 00 00 00 사용되지않음
24 4 80 00 80 00 항상 이값이어야함
28 8 FF F7 34 0C 총섹터수 (C34F7FFh : 204,797,951)
00 00 00 00
30 8 00 00 0C 00 MFT의 시작클러스터값
00 00 00 00
38 8 02 00 00 00 MFT의 복사본의 위치
00 00 00 00
40 1 F6 MFT(Master File Table) record의 크기
양수(1h ~ 7Fh) : mft record당 클러스터수
음수(80h ~ FFh) : mft record의 크기 ( 2의 누승)
여기서는 F6 는 -10이고 2의 10승하면 1024바이트
41 3 00 00 00 사용되지 않음
44 1 01 index buffer당 클러스터갯수
45 3 00 00 00 사용되지 않음
48 8 65 6B 45 8A NTFS Volume serial number
A9 45 8A F2 cmd창에서 dir했을때 나타나는 volume serial number가
이 값의 하위4바이트값이다(8A45-6B65)
50 4 00 00 00 00 사용되지 않음
------------------------------------------
BPB(Bios Parameter Block)의 끝
------------------------------------------
54 138 xx..xx 부트코드
18C 108 xx..xx 에러메시지
1F8 4 8C A9 BE D6 네개의 에러메시지 각각의 포인터
1FC 2 00 00 사용되지않음
1FE 2 55 AA 매직넘버. 부트섹터임을 표시함
---------------------------------------------------------------
부트섹터코드가 하는일을 개략적으로 이야기하면 이렇다
01. 부트섹터의 03h번지에 NTFS 라는 글자가 없으면 에러메시지를 출력한다음 멈춤
02. 부팅하드디스크가 LBA모드를 지원하지 않으면 에러메시지를 출력한다음 멈춤
03. 부팅하드디스크 1섹터의 크기가 512바이트가 아니라면 에러메시지출력후 멈춤
04. 부팅하드디스크의 부트섹터다음 섹터부터 16섹터 (8096바이트)를 7e00h번지로 읽어온다.
05. 메인보드의 바이오스가 TCG를 지원하면 모종의 처리를 한다.
06. 메모리 특정영역을 0으로 초기화한다음 [03]에서 읽어온 데이타의 코드영역으로 점프한다.
아래 코드는 borg 를 사용해서 부트섹터를 16bit 어셈블리코드로 나타낸것이다.
옵셋을 7c00h 로 잡은건 mbr에서 이 부트섹터 512바이트를 7c00h로 읽어들이기 때문이다.
; Borg Disassembler v2.28
;
0000:7c00 ;-----------------------------------------------------------------------
0000:7c00 ;Segment : 0000h Offset : 7c00h Size : 200h
0000:7c00 ;16-bit Code
0000:7c00 ;-----------------------------------------------------------------------
0000:7c00 start: <--시작
0000:7c00 eb52 jmp start1
0000:7c02 90 nop
0000:7c03 4e54465320202020 db "NTFS " ; oem id
0000:7c0b 0200 ; 섹터당 바이트수
0000:7c0d 08
0000:7c0e 00 ; 부팅디스크의 id를 저장
; 80h[첫번째hdd], 81h[두번째hdd]
0000:7c0f 0000 ; 20h값을 보관
; 읽어서 보관될곳의 세그먼트주소의 증가값으로 쓰인다
; 즉 세그먼트이기 때문에 20h x 16 = 200h (512)만큼 증가한다는 의미이다.
; 512바이트 읽어와서 메모리 0 번지에 저장된다면
; 그 다음번에는 (0 + 512) 번지에 저장된다는 뜻이다.
; 읽어올 하드디스크의 섹터위치값을 표시할때 [베이스+인텍스]방식으로 한다.
; [7c1ch] + [7c11h] ---> hdd sector
; 베이스 인텍스
; 베이스는 고정되어있고 인텍스값은 차례로 1씩 증가하면서 섹터값을 증가시킨다.
; 여기에서는 [7c1ch] = 800h 이고 [7c11h]는 0 이다.
;
0000:7c11 00000000 ; hdd sector 지정 인텍스
0000:7c15 f8
0000:7c16 0000 ; [1섹터읽기]를 반복할 햇수
0000:7c18 00ff003f
0000:7c1c 08000000 ; hdd sector 지정 베이스
0000:7c20 00 00 00 00 00 80 00 80 00 ff f7 34 0c 00 00 00 00 00
0000:7c31 00 0c 00 00 00 00 00 02 00 00 00 00 00 00 00 f6 00 00 00 01
0000:7c45 00 00 00 65 6b 45 8a a9 45 8a f2 00 00 00 00
0000:7c54 start1:
0000:7c54 fa cli
0000:7c55 33c0 xor ax, ax
0000:7c57 8ed0 mov ss, ax
0000:7c59 bc007c mov sp, 7c00h
; 스택의 꼭대기를 부트코드의 시작주소로 했다.
; 스택은 아래로 커가는 것이기 때문에 부트코드와
; 간섭없이 7c00h(31,744)바이트의 공간을 확보했다
0000:7c5c fb sti
0000:7c5d 68c007 push 7c0h
0000:7c60 1f pop ds
; data segment 를 7c0h로 했다.
; 16비트 segment:offset 주소선택방식에서는
; 전체오프셋은 segment * 16h + offset 이니까
; 즉 segment를 왼쪽으로 4비트만큼 옮긴것과 같으니까
; 7c0:66 --> 7c66 와 같아진다.
0000:7c61 1e push ds
0000:7c62 686600 push 66h
0000:7c65 cb retf
; 7c66h 로 점프, 바로 아래쪽
0000:7c66 88160e00 mov [0eh], dl ; dl= 80h[first] or 81h[second]
0000:7c6a 66813e03004e544653 cmp dword ptr [03h], 5346544eh ; NTFS
0000:7c73 7515 jnz go_error
0000:7c75 b441 mov ah, 41h
0000:7c77 bbaa55 mov bx, 55aah
0000:7c7a cd13 int 13h
; extended disk ?
0000:7c7c 720c jc go_error
0000:7c7e 81fb55aa cmp bx, 0aa55h
0000:7c82 7506 jnz go_error
0000:7c84 f7c10100 test cx, 01h
0000:7c88 7503 jnz is_extended_disk
0000:7c8a go_error:
0000:7c8a e9dd00 jmp is_error
0000:7c8d is_extended_disk:
;----------------------------------------------------------------
; int 13h, ah = 48h : extended read drive
; dl = drive index : 80h = first hdd, 81h = second hdd
; ds:si : 읽어온 데이타가 보관될 곳
; -------------------------------------------------------
; carry : 1이면 error 발생
; 00h - 01h : 읽어온 데이타의 크기
; 02h - 03h : flags
; 04h - 07h : 물리적 실린더수(0부터 시작)
; 08h - 0bh : 물리적 헤드수 (0부터 시작)
; 0ch - 0fh : 트랙당 섹터수 (1부터 시작)
; 10h - 17h : 전체 섹터수 (0부터 시작)
; 18h - 19h : 섹터당 바이트수
; 1ah - 1dh : EDD(Enhanced Disk Drive)의 추가정보 포인트
; : 사양에는 있으나 사용되고 있지않음
; -------------------------------------------------------
; 여기서는 18h에 담길 [섹터당 바이트수: 200h ]만을 사용함
;-------------------------------------------------------------
0000:7c8d 1e push ds ;1
0000:7c8e 83ec18 sub sp, 18h ;2
0000:7c91 681a00 push 1ah ;3
0000:7c94 b448 mov ah, 48h
0000:7c96 8a160e00 mov dl, [0eh]
0000:7c9a 8bf4 mov si, sp ;3
0000:7c9c 16 push ss
0000:7c9d 1f pop ds
0000:7c9e cd13 int 13h
0000:7ca0 9f lahf
0000:7ca1 83c418 add sp, 18h ;4
--------------------------------------------
; 위의 명령이 실행되는 동안의 스택의 변화도
--------------------------------------------
00h ds <-- sp(1)
----------------------------------------
-02h 섹터당 바이트수 <-- sp(4)
-04h 전체 섹터수
-0ch 트랙당 섹터수
.
.
-16h
-18h <-- sp(2)
-1ah 1ah <-- sp(3)=si
----------------------------------------
0000:7ca4 9e sahf
0000:7ca5 58 pop ax
; 섹터당 바이트수 200h(512) 가 ax에 담겼다
0000:7ca6 1f pop ds
; ds는 변하지 않았다. 7c0h 그대로
0000:7ca7 72e1 jc go_error
0000:7ca9 3b060b00 cmp ax, [0bh]
0bh번지의 값은 200h(512)이다.
0000:7cad 75db jnz go_error
0000:7caf a30f00 mov word ptr[0fh], ax
0000:7cb2 c12e0f0004 shr word ptr[0fh], 04h
; 200h/10h = 20h
0000:7cb7 1e push ds
0000:7cb8 5a pop dx ; dx = ds = 7c0h
0000:7cb9 33db xor bx, bx
; es:bx 섹터를 읽어서보관될곳의 offset
0000:7cbb b90020 mov cx, 2000h
0000:7cbe 2bc8 sub cx, ax
0000:7cc0 66ff061100 inc dword ptr [11h]
; 하드디스크 섹터를 읽을 인텍스값
; 0 -> 1 -> 2 --> 3 ..
0000:7cc5 repeat_read:
0000:7cc5 03160f00 add dx, [0fh]
0000:7cc9 8ec2 mov es, dx
; es:bx = 7e0:00 = 7e00h 번지에 보관하라
; 그다음번에는 8000h
; 8200h , 8400h , 8600h...9e00h까지
; 총 16섹터 = 8096바이트를 읽어온다.
; 참고로 7c00h 에서 7dffh 까지에는
; 지금 읽고있는 이 부트섹터 512바이트가
; 보관되어있다.
0000:7ccb ff061600 inc word ptr [16h]
; 0 에서 1로 바뀐다
; read_sector에서 다시 0으로 바뀐다.
0000:7ccf e84b00 call read_sector
0000:7cd2 2bc8 sub cx, ax
0000:7cd4 77ef ja repeat_read
; (2000h/200h = 10h)즉 16번 반복
; 16섹터를 읽었다
; 여기서부터는 TCG관련인데 mbr코드에 나타난것과 똑같다.
;
0000:7cd6 b800bb mov ax, 0bb00h
0000:7cd9 cd1a int 1ah
; TCG(Trusted Computing Group) call이다
; 지원하면 eax = 0
; ebx = 41504354h('TCPA')
; ch:cL = TCG 바이오스 버전 1.2
0000:7cdb 6623c0 and eax, eax
0000:7cde 752d jnz no_support_tcg
0000:7ce0 6681fb54435041 cmp ebx, 41504354h
0000:7ce7 7524 jnz no_support_tcg
0000:7ce9 81f90201 cmp cx, 102h
0000:7ced 721e jc no_support_tcg
; TPM 1.2가 발견되었고 TCG_CompactHashLogExtendEvent를 실행?
0000:7cef 16 push ss
0000:7cf0 6807bb push 0bb07h
0000:7cf3 16 push ss
0000:7cf4 68700e push 0e70h
0000:7cf7 16 push ss
0000:7cf8 680900 push 09h
0000:7cfb 6653 push ebx
0000:7cfd 6653 push ebx
0000:7cff 6655 push ebp
0000:7d01 16 push ss
0000:7d02 16 push ss
0000:7d03 16 push ss
0000:7d04 68b801 push 1b8h
0000:7d07 6661 popad
0000:7d09 0e push cs
0000:7d0a 07 pop es
0000:7d0b cd1a int 1ah
0000:7d0d no_support_tcg:
0000:7d0d 33c0 xor ax, ax
0000:7d0f bf2810 mov di, 1028h
0000:7d12 b9d80f mov cx, 0fd8h
0000:7d15 fc cld
0000:7d16 f3aa rep stosb
; es:di 가 가르키는곳을 cx의 값만큼 al값으로
; 초기화한다
;
0000:7d18 e95f01 jmp next_bootsector
; bootmgr의 그 다음 블럭으로 제어가 넘어간다.
0000:7d1b 90 nop
0000:7d1c 90 nop
;-----------------------------------------------------------------------------
0000:7d1d read_sector:
;-----------------------------------------------------------------------------
; 이 함수는 한섹터를 읽고
; 섹터포인터와 주소포인터를 1증가시킨다.
;
; 결과적으로 보면,
; 800h ~ 80fh 까지 한섹터씩 16섹터(8192바이트)를 읽어와서
; 7e00h 부터 시작해서 9effh 번지까지 보관
; 800h는 논리적섹터로 보면 부트섹트 바로 다음의 섹터가 된다.
;-----------------------------------------------------------------------------
; extended read sector from drive
; int 13h ah=42h
;--------------------------------------------------------
; dl - drive index (1st hdd = 80h, 2st hdd = 81h)
; ds:si - DAP의 주소
;--------------------------------------------------------
; DAP ( Disk Address Packet )
;--------------------------------------------------------
; 0 : 1byte : dap의 크기 = 10h
; 1 : 1byte : 0 이어야 함
; 2~3 : 2byte : 읽을 섹터수 = 1
; 4~7 : 4byte : 읽어서 보관할 곳 = es:bx
; 8~f : 8byte : lba로 표시된 읽을곳 = eax = [11h]+[1ch]
;--------------------------------------------------------
; cf : 1=에러가 발생
;--------------------------------------------------------
; [11h] + [1ch] : 읽을 섹터의 위치
; [16h] : 1섹터를 읽는일을 몇번 반복할까, 그횟수를 나타냄
;-----------------------------------------------------------------------------
0000:7d1d 6660 pushad
0000:7d1f 1e push ds
0000:7d20 06 push es
0000:7d21 read_sector_1:
0000:7d21 66a11100 mov eax, word ptr[11h]
0000:7d25 6603061c00 add eax, [1ch]
; eax = [11h] + [1ch]
0000:7d2a 1e push ds
0000:7d2b 666800000000 push 00h
0000:7d31 6650 push eax ; 읽을 섹터(lba)
0000:7d33 06 push es ; 저장될 segment
0000:7d34 53 push bx ; 저장될 offset
0000:7d35 680100 push 01h ; 1 sector 만큼 읽는다
0000:7d38 681000 push 10h ; dap의 크기
0000:7d3b b442 mov ah, 42h ; read disk
0000:7d3d 8a160e00 mov dl, [0eh] ; 부팅디스크
0000:7d41 16 push ss
0000:7d42 1f pop ds
0000:7d43 8bf4 mov si, sp
0000:7d45 cd13 int 13h
; 스택을 비운다
0000:7d47 6659 pop ecx ; 4byte
0000:7d49 5b pop bx ; bx <- bx
0000:7d4a 5a pop dx ; dx <- es
0000:7d4b 6659 pop ecx ; 4byte
0000:7d4d 6659 pop ecx ; 4byte
0000:7d4f 1f pop ds ; ds <- ds
0000:7d50 0f821600 jc is_error
0000:7d54 66ff061100 inc dword ptr [11h] ; 읽을 next sector
0000:7d59 03160f00 add dx, [0fh] ; [0fh]=20h
0000:7d5d 8ec2 mov es, dx ; 저장될 다음 주소
0000:7d5f ff0e1600 dec word ptr [16h]
0000:7d63 75bc jnz read_sector_1
0000:7d65 07 pop es
0000:7d66 1f pop ds
0000:7d67 6661 popad
0000:7d69 c3 ret
0000:7d6a is_error:
0000:7d6a a0f801 mov al, byte ptr word ptr[1f8h] ;first msg
0000:7d6d e80900 call display_error
0000:7d70 a0fb01 mov al, byte ptr word ptr[1fbh] ;fourth msg
0000:7d73 e80300 call display_error
0000:7d76 system_halt:
0000:7d76 f4 hlt
0000:7d77 ebfd jmp system_halt
0000:7d79 display_error:
0000:7d79 b401 mov ah, 01h
0000:7d7b 8bf0 mov si, ax
0000:7d7d next_byte:
0000:7d7d ac lodsb
0000:7d7e 3c00 cmp al, 00h
0000:7d80 7409 jz exit_display_error
0000:7d82 b40e mov ah, 0eh
0000:7d84 bb0700 mov bx, 07h
0000:7d87 cd10 int 10h
0000:7d89 ebf2 jmp next_byte
0000:7d8b exit_display_error:
0000:7d8b c3 ret
error_msg:
;------------------------------first error message-----------------------------------------
0000:7d8c 0d0a41206469736b2072656164206572726f72206f6363757272656400
db "..A disk read error occured."
;------------------------------second error message---------------------------------------
0000:7da9 0d0a424f4f544d4752206973206d697373696e6700
db "..BOOTMDR is missing."
;------------------------------third error message-----------------------------------------
0000:7dbe 0d0a424f4f544d475220697320636f6d7072657373656400
db "..BOOTMDR is compressed."
;------------------------------fourth error message-----------------------------------------
0000:7dd6 0d0a5072657373204374726c2b416c742b44656c20746f20726573746172740d0a00
db "..Press Ctrl+Alt+Del to restart..."
;-----------------------------------------------------------------------
error_ptr:
0000:7df8 8ca9bed6
위의 에러메시지의 시작주소를 나타낸다.
이건 mbr코드에서 본 바있다.
0000:7dfc 0000
0000:7dfe 55aa ; signature id (magic number)

------------------------------------------
BPB(Bios Parameter Block)의 끝
------------------------------------------
; Borg Disassembler v2.28
;
0000:7c00 ;-----------------------------------------------------------------------
0000:7c00 ;Segment : 0000h Offset : 7c00h Size : 200h
0000:7c00 ;16-bit Code
0000:7c00 ;-----------------------------------------------------------------------
0000:7c00 start: <--시작
0000:7c00 eb52 jmp start1
0000:7c02 90 nop
0000:7c03 4e54465320202020 db "NTFS " ; oem id
0000:7c0b 0200 ; 섹터당 바이트수
0000:7c0d 08
0000:7c0e 00 ; 부팅디스크의 id를 저장
; 80h[첫번째hdd], 81h[두번째hdd]
0000:7c0f 0000 ; 20h값을 보관
; 읽어서 보관될곳의 세그먼트주소의 증가값으로 쓰인다
; 즉 세그먼트이기 때문에 20h x 16 = 200h (512)만큼 증가한다는 의미이다.
; 512바이트 읽어와서 메모리 0 번지에 저장된다면
; 그 다음번에는 (0 + 512) 번지에 저장된다는 뜻이다.
; 읽어올 하드디스크의 섹터위치값을 표시할때 [베이스+인텍스]방식으로 한다.
; [7c1ch] + [7c11h] ---> hdd sector
; 베이스 인텍스
; 베이스는 고정되어있고 인텍스값은 차례로 1씩 증가하면서 섹터값을 증가시킨다.
; 여기에서는 [7c1ch] = 800h 이고 [7c11h]는 0 이다.
;
0000:7c11 00000000 ; hdd sector 지정 인텍스
0000:7c15 f8
0000:7c16 0000 ; [1섹터읽기]를 반복할 햇수
0000:7c18 00ff003f
0000:7c1c 08000000 ; hdd sector 지정 베이스
0000:7c20 00 00 00 00 00 80 00 80 00 ff f7 34 0c 00 00 00 00 00
0000:7c31 00 0c 00 00 00 00 00 02 00 00 00 00 00 00 00 f6 00 00 00 01
0000:7c45 00 00 00 65 6b 45 8a a9 45 8a f2 00 00 00 00
0000:7c54 start1:
0000:7c54 fa cli
0000:7c55 33c0 xor ax, ax
0000:7c57 8ed0 mov ss, ax
0000:7c59 bc007c mov sp, 7c00h
; 스택의 꼭대기를 부트코드의 시작주소로 했다.
; 스택은 아래로 커가는 것이기 때문에 부트코드와
; 간섭없이 7c00h(31,744)바이트의 공간을 확보했다
0000:7c5c fb sti
0000:7c5d 68c007 push 7c0h
0000:7c60 1f pop ds
; data segment 를 7c0h로 했다.
; 16비트 segment:offset 주소선택방식에서는
; 전체오프셋은 segment * 16h + offset 이니까
; 즉 segment를 왼쪽으로 4비트만큼 옮긴것과 같으니까
; 7c0:66 --> 7c66 와 같아진다.
0000:7c61 1e push ds
0000:7c62 686600 push 66h
0000:7c65 cb retf
; 7c66h 로 점프, 바로 아래쪽
0000:7c66 88160e00 mov [0eh], dl ; dl= 80h[first] or 81h[second]
0000:7c6a 66813e03004e544653 cmp dword ptr [03h], 5346544eh ; NTFS
0000:7c73 7515 jnz go_error
0000:7c75 b441 mov ah, 41h
0000:7c77 bbaa55 mov bx, 55aah
0000:7c7a cd13 int 13h
; extended disk ?
0000:7c7c 720c jc go_error
0000:7c7e 81fb55aa cmp bx, 0aa55h
0000:7c82 7506 jnz go_error
0000:7c84 f7c10100 test cx, 01h
0000:7c88 7503 jnz is_extended_disk
0000:7c8a go_error:
0000:7c8a e9dd00 jmp is_error
0000:7c8d is_extended_disk:
;----------------------------------------------------------------
; int 13h, ah = 48h : extended read drive
; dl = drive index : 80h = first hdd, 81h = second hdd
; ds:si : 읽어온 데이타가 보관될 곳
; -------------------------------------------------------
; carry : 1이면 error 발생
; 00h - 01h : 읽어온 데이타의 크기
; 02h - 03h : flags
; 04h - 07h : 물리적 실린더수(0부터 시작)
; 08h - 0bh : 물리적 헤드수 (0부터 시작)
; 0ch - 0fh : 트랙당 섹터수 (1부터 시작)
; 10h - 17h : 전체 섹터수 (0부터 시작)
; 18h - 19h : 섹터당 바이트수
; 1ah - 1dh : EDD(Enhanced Disk Drive)의 추가정보 포인트
; : 사양에는 있으나 사용되고 있지않음
; -------------------------------------------------------
; 여기서는 18h에 담길 [섹터당 바이트수: 200h ]만을 사용함
;-------------------------------------------------------------
0000:7c8d 1e push ds ;1
0000:7c8e 83ec18 sub sp, 18h ;2
0000:7c91 681a00 push 1ah ;3
0000:7c94 b448 mov ah, 48h
0000:7c96 8a160e00 mov dl, [0eh]
0000:7c9a 8bf4 mov si, sp ;3
0000:7c9c 16 push ss
0000:7c9d 1f pop ds
0000:7c9e cd13 int 13h
0000:7ca0 9f lahf
0000:7ca1 83c418 add sp, 18h ;4
--------------------------------------------
; 위의 명령이 실행되는 동안의 스택의 변화도
--------------------------------------------
00h ds <-- sp(1)
----------------------------------------
-02h 섹터당 바이트수 <-- sp(4)
-04h 전체 섹터수
-0ch 트랙당 섹터수
.
.
-16h
-18h <-- sp(2)
-1ah 1ah <-- sp(3)=si
----------------------------------------
0000:7ca4 9e sahf
0000:7ca5 58 pop ax
; 섹터당 바이트수 200h(512) 가 ax에 담겼다
0000:7ca6 1f pop ds
; ds는 변하지 않았다. 7c0h 그대로
0000:7ca7 72e1 jc go_error
0000:7ca9 3b060b00 cmp ax, [0bh]
0000:7cad 75db jnz go_error
0000:7caf a30f00 mov word ptr[0fh], ax
0000:7cb2 c12e0f0004 shr word ptr[0fh], 04h
; 200h/10h = 20h
0000:7cb7 1e push ds
0000:7cb8 5a pop dx ; dx = ds = 7c0h
0000:7cb9 33db xor bx, bx
; es:bx 섹터를 읽어서보관될곳의 offset
0000:7cbb b90020 mov cx, 2000h
0000:7cbe 2bc8 sub cx, ax
0000:7cc0 66ff061100 inc dword ptr [11h]
; 하드디스크 섹터를 읽을 인텍스값
; 0 -> 1 -> 2 --> 3 ..
0000:7cc5 repeat_read:
0000:7cc5 03160f00 add dx, [0fh]
0000:7cc9 8ec2 mov es, dx
; es:bx = 7e0:00 = 7e00h 번지에 보관하라
; 그다음번에는 8000h
; 8200h , 8400h , 8600h...9e00h까지
; 총 16섹터 = 8096바이트를 읽어온다.
; 참고로 7c00h 에서 7dffh 까지에는
; 지금 읽고있는 이 부트섹터 512바이트가
; 보관되어있다.
0000:7ccb ff061600 inc word ptr [16h]
; 0 에서 1로 바뀐다
; read_sector에서 다시 0으로 바뀐다.
0000:7ccf e84b00 call read_sector
0000:7cd2 2bc8 sub cx, ax
0000:7cd4 77ef ja repeat_read
; (2000h/200h = 10h)즉 16번 반복
; 16섹터를 읽었다
; 여기서부터는 TCG관련인데 mbr코드에 나타난것과 똑같다.
;
0000:7cd6 b800bb mov ax, 0bb00h
0000:7cd9 cd1a int 1ah
; TCG(Trusted Computing Group) call이다
; 지원하면 eax = 0
; ebx = 41504354h('TCPA')
; ch:cL = TCG 바이오스 버전 1.2
0000:7cdb 6623c0 and eax, eax
0000:7cde 752d jnz no_support_tcg
0000:7ce0 6681fb54435041 cmp ebx, 41504354h
0000:7ce7 7524 jnz no_support_tcg
0000:7ce9 81f90201 cmp cx, 102h
0000:7ced 721e jc no_support_tcg
; TPM 1.2가 발견되었고 TCG_CompactHashLogExtendEvent를 실행?
0000:7cef 16 push ss
0000:7cf0 6807bb push 0bb07h
0000:7cf3 16 push ss
0000:7cf4 68700e push 0e70h
0000:7cf7 16 push ss
0000:7cf8 680900 push 09h
0000:7cfb 6653 push ebx
0000:7cfd 6653 push ebx
0000:7cff 6655 push ebp
0000:7d01 16 push ss
0000:7d02 16 push ss
0000:7d03 16 push ss
0000:7d04 68b801 push 1b8h
0000:7d07 6661 popad
0000:7d09 0e push cs
0000:7d0a 07 pop es
0000:7d0b cd1a int 1ah
0000:7d0d no_support_tcg:
0000:7d0d 33c0 xor ax, ax
0000:7d0f bf2810 mov di, 1028h
0000:7d12 b9d80f mov cx, 0fd8h
0000:7d15 fc cld
0000:7d16 f3aa rep stosb
; es:di 가 가르키는곳을 cx의 값만큼 al값으로
; 초기화한다
;
0000:7d18 e95f01 jmp next_bootsector
; bootmgr의 그 다음 블럭으로 제어가 넘어간다.
0000:7d1b 90 nop
0000:7d1c 90 nop
;-----------------------------------------------------------------------------
0000:7d1d read_sector:
;-----------------------------------------------------------------------------
; 이 함수는 한섹터를 읽고
; 섹터포인터와 주소포인터를 1증가시킨다.
;
; 결과적으로 보면,
; 800h ~ 80fh 까지 한섹터씩 16섹터(8192바이트)를 읽어와서
; 7e00h 부터 시작해서 9effh 번지까지 보관
;-----------------------------------------------------------------------------
; extended read sector from drive
; int 13h ah=42h
;--------------------------------------------------------
; dl - drive index (1st hdd = 80h, 2st hdd = 81h)
; ds:si - DAP의 주소
;--------------------------------------------------------
; DAP ( Disk Address Packet )
;--------------------------------------------------------
; 0 : 1byte : dap의 크기 = 10h
; 1 : 1byte : 0 이어야 함
; 2~3 : 2byte : 읽을 섹터수 = 1
; 4~7 : 4byte : 읽어서 보관할 곳 = es:bx
; 8~f : 8byte : lba로 표시된 읽을곳 = eax = [11h]+[1ch]
;--------------------------------------------------------
; cf : 1=에러가 발생
;--------------------------------------------------------
; [11h] + [1ch] : 읽을 섹터의 위치
; [16h] : 1섹터를 읽는일을 몇번 반복할까, 그횟수를 나타냄
;-----------------------------------------------------------------------------
0000:7d1d 6660 pushad
0000:7d1f 1e push ds
0000:7d20 06 push es
0000:7d21 read_sector_1:
0000:7d21 66a11100 mov eax, word ptr[11h]
0000:7d25 6603061c00 add eax, [1ch]
; eax = [11h] + [1ch]
0000:7d2a 1e push ds
0000:7d2b 666800000000 push 00h
0000:7d31 6650 push eax ; 읽을 섹터(lba)
0000:7d33 06 push es ; 저장될 segment
0000:7d34 53 push bx ; 저장될 offset
0000:7d35 680100 push 01h ; 1 sector 만큼 읽는다
0000:7d38 681000 push 10h ; dap의 크기
0000:7d3b b442 mov ah, 42h ; read disk
0000:7d3d 8a160e00 mov dl, [0eh] ; 부팅디스크
0000:7d41 16 push ss
0000:7d42 1f pop ds
0000:7d43 8bf4 mov si, sp
0000:7d45 cd13 int 13h
; 스택을 비운다
0000:7d47 6659 pop ecx ; 4byte
0000:7d49 5b pop bx ; bx <- bx
0000:7d4a 5a pop dx ; dx <- es
0000:7d4b 6659 pop ecx ; 4byte
0000:7d4d 6659 pop ecx ; 4byte
0000:7d4f 1f pop ds ; ds <- ds
0000:7d50 0f821600 jc is_error
0000:7d54 66ff061100 inc dword ptr [11h] ; 읽을 next sector
0000:7d59 03160f00 add dx, [0fh] ; [0fh]=20h
0000:7d5d 8ec2 mov es, dx ; 저장될 다음 주소
0000:7d5f ff0e1600 dec word ptr [16h]
0000:7d63 75bc jnz read_sector_1
0000:7d65 07 pop es
0000:7d66 1f pop ds
0000:7d67 6661 popad
0000:7d69 c3 ret
0000:7d6a is_error:
0000:7d6a a0f801 mov al, byte ptr word ptr[1f8h] ;first msg
0000:7d6d e80900 call display_error
0000:7d70 a0fb01 mov al, byte ptr word ptr[1fbh] ;fourth msg
0000:7d73 e80300 call display_error
0000:7d76 system_halt:
0000:7d76 f4 hlt
0000:7d77 ebfd jmp system_halt
0000:7d79 display_error:
0000:7d79 b401 mov ah, 01h
0000:7d7b 8bf0 mov si, ax
0000:7d7d next_byte:
0000:7d7d ac lodsb
0000:7d7e 3c00 cmp al, 00h
0000:7d80 7409 jz exit_display_error
0000:7d82 b40e mov ah, 0eh
0000:7d84 bb0700 mov bx, 07h
0000:7d87 cd10 int 10h
0000:7d89 ebf2 jmp next_byte
0000:7d8b exit_display_error:
0000:7d8b c3 ret
error_msg:
;------------------------------first error message-----------------------------------------
0000:7d8c 0d0a41206469736b2072656164206572726f72206f6363757272656400
db "..A disk read error occured."
;------------------------------second error message---------------------------------------
0000:7da9 0d0a424f4f544d4752206973206d697373696e6700
db "..BOOTMDR is missing."
;------------------------------third error message-----------------------------------------
0000:7dbe 0d0a424f4f544d475220697320636f6d7072657373656400
db "..BOOTMDR is compressed."
;------------------------------fourth error message-----------------------------------------
0000:7dd6 0d0a5072657373204374726c2b416c742b44656c20746f20726573746172740d0a00
db "..Press Ctrl+Alt+Del to restart..."
;-----------------------------------------------------------------------
error_ptr:
0000:7df8 8ca9bed6
위의 에러메시지의 시작주소를 나타낸다.
0000:7dfc 0000
0000:7dfe 55aa ; signature id (magic number)