2009-10-11 4 views
9

나는 NASM이 나에게 어떤 오류도주지 않았기 때문에 나는 지금 몇 주 동안 붙어 있었고 어디에서 잘못 될지 모른다. 주석은 주석 때문에 꽤 자명하다. NASM 어셈블리에서 BIOS int 13h를 사용하여 디스크에서 커널을로드하는 방법은 무엇입니까?

은 BIOS에서로드되는 코드입니다

;-------------------------------------------- 
; 'boot.asm' 
; loaded from BIOS 

[org 0x7C00] 
[bits 16] 

;-------------------------------------------- 

main: 
    mov ah, 0x0E ; print function 
    mov al, '.' ; ascii char 
    int 0x10 ; IO int 

resetdisk: 
    mov ah, 0x00 ; reset function 
    mov dl, 0x00 ; drive 
    int 0x13 ; disk int 
    jc resetdisk 

readdisk: 
    mov bx, 0x8000 ; segment 
    mov es, bx 
    mov bx, 0x0000 ; offset 

    mov ah, 0x02 ; read function 
    mov al, 0x03 ; sectors 
    mov ch, 0x00 ; cylinder 
    mov cl, 0x02 ; sector 
    mov dh, 0x00 ; head 
    mov dl, 0x00 ; drive 
    int 0x13 ; disk int 
    jc readdisk 
    jmp [es:bx] ; buffer 

;-------------------------------------------- 

times 510 - ($ - $$) db 0x00 
db 0x55, 0xAA 

이 있어야 코드 (그러나입니다) 어떤 도움이 많이 주시면 감사하겠습니다

;-------------------------------------------- 
; 'load.asm' 
; loaded from 'boot.asm' 

[org 0x8000] 
[bits 16] 

;-------------------------------------------- 

main: 
    mov ah, 0x0E ; print function 
    mov al, '.' ; ascii char 
    int 0x10 ; IO int 

    jmp $ ; hang 

로드 .

패트릭

+0

제발 틀렸어.하지만'jmp $'대신에'cli'로 인터럽트를 지우고'hlt'로하면 CPU를 멈추게 하는게 더 나을 것입니다. 이 방법을 사용하면 많은 CPU 시간을 소비하지 않아도됩니다. – kaneda

+0

최소 작동 가스 예 : https://github.com/cirosantilli/x86-bare-metal-examples/blob/1f6af9021283dc01f2247efbb6aa9217363fbf07/bios_disk_load.S –

답변

7

jmp [es:bx]es:bx으로 점프하지 않습니다. 이 명령은 es:bx이라는 단어에 저장된 주소로 거의 점프합니다. 이것이 많은 오래된 어셈블러가 jmp word ptr [es:bx] 또는 심지어 jmp near ptr [es:bx]과 같은 이런 종류의 명령어를 쓰게 한 이유입니다. 이 일이 어떻게 될지 명확 해집니다.당신이 아마 여기에 원하는 것은 고정 된 위치에 멀리 점프입니다 :

; jmp far 8000:0000 
db 0eah 
dw 00000h ; offset 
dw 08000h ; segment 

당신이 es:bx로 이동하려는 경우, retf를 사용하는 코드는 '아무튼 왜

push es 
push bx 
retf 
+0

이게 옳은 것처럼 보이지만 작동시키지 못합니다. 자습서/문서에 대한 링크가 있습니까? –

+0

아니요 : S, 작동합니다. 그냥 'a :'대신 '.img'를 사용했습니다. 나는 그것을 바꿔야 할 것이다. –

+2

그냥 "jmp 0x0000 : 0x8000"을 직접 nasm에서 사용하지 않는 것이 어떻습니까? 더 읽기 쉽습니다. – SecurityMatt

2

난 당신이 코드를 달성하기 위해 노력하고있는 것을 잘 모르겠지만, 내가 제대로 이해한다면, 당신은 위치 0x8000을에 디스크에서 몇 섹터를 읽고 그 코드를 실행하려면?

그런 경우 해당 위치로 CALL/JUMP를 명시 적으로 만들어야합니다. BIOS가 해당 코드를 호출하지 않습니다. 부팅시, BIOS가 초기화되면 명령 포인터 IP를 0x7c00 주소로 설정합니다. 그러면 CPU가 순차적으로 코드를 실행하기 시작합니다. 따라서 JMP/CALL없이 0x8000을 실행하지 않고 0x7000에서 0x8000 사이의 모든 메모리 주소를 실행할 때까지 코드를 실행하지 않습니다.

따라서 해결책은 jc readdisk 다음에 jmp 또는 call 명령을 사용하십시오.

제 이해가 잘못 되었다면 사과드립니다. 희망이 도움이됩니다.

+0

JMP는 JC readdisk 이후 : JMP [ES : BX] ES : bx는 코드 버퍼입니다 –

+0

죄송합니다. 한 가지, 코드를 살펴보십시오. load.asm 파일이 섹터 2에 있는지 확인 하시겠습니까? –

+0

예, 부팅 후 섹터에서 win32와 dd를 사용합니다. –

1

OS를 부팅하는 데 플로피 디스크를 사용하고 있는지 잘 모르겠지만 사용하고 있다면 ORG 및 비트 선언 다음에 몇 가지 사항을 선언 하시길 바랍니다 (매우 중요합니다) :

JMP short main ; Jump past disk description section 
NOP    ; Pad out before disk description 

; ------------------------------------------------------------------ 
; Disk description table, to make it a valid floppy 
; Note: some of these values are hard-coded in the source! 
; Values are those used by IBM for 1.44 MB, 3.5 diskette 

OEMLabel   db "BERL OS" ; Disk label - 8 chars 
BytesPerSector  dw 512   ; Bytes per sector 
SectorsPerCluster db 1   ; Sectors per cluster 
ReservedForBoot  dw 1   ; Reserved sectors for boot record 
NumberOfFats  db 2   ; Number of copies of the FAT 
RootDirEntries  dw 224   ; Number of entries in root dir 
LogicalSectors  dw 2880   ; Number of logical sectors 
MediumByte   db 0F0h   ; Medium descriptor byte 
SectorsPerFat  dw 9   ; Sectors per FAT 
SectorsPerTrack  dw 18   ; Sectors per track (36/cylinder) 
Sides    dw 2   ; Number of sides/heads 
HiddenSectors  dd 0   ; Number of hidden sectors 
LargeSectors  dd 0   ; Number of LBA sectors 
DriveNo    dw 0   ; Drive No: 0 
Signature   db 41   ; Drive signature: 41 for floppy 
VolumeID   dd 00000000h ; Volume ID: any number 
VolumeLabel   db "BERL OS" ; Volume Label: any 11 chars 
FileSystem   db "FAT12"  ; File system type: don't change! 

; End of the disk description table 
; ------------------------------------------------------------------ 

이 정보를 삽입하는 것이 좋습니다.

감사합니다.

+0

이것은 정말로 중요하지 않습니다. 그것은 파일 시스템 및 BIOS를위한 것입니다. –

+0

좋아, 이제는 기본 아이디어를 안다. 감사합니다 –

2

INT13이있는 하나의 잡아 당김은 헤드와 트랙 번호가 0에서 시작하지만 어떤 이유로 든 섹터 번호가 1부터 시작한다는 것입니다. 섹터 작성 유틸리티가이 번호 매기기 구성표와 일치하는지 확인할 수 있습니다.

질문 :

  • 부팅 할 때 얼마나 많은 점을 볼 수 있습니까?
  • 플로피 모터가 작동합니까?
+0

예, 나는 그것을 확인했습니다. 또한 에뮬레이터 (win32 qemu)를 사용하므로 플로피 모터가 작동하지 않습니다. –

0

잘 모르겠어요 (디스크, 메모리 덤프 등) 전체 환경을 점검 할 수 없기 때문에 작업하지 않아도된다.하지만 내가 말할 수있는 것은 코드가 잘못되었다는 것이다. 두 번째 프로그램은 0x8000 (즉, 0rg 0x8000을 사용하는 지점입니까?)이 아닌 0x80000에로드하고 있습니다.

이유 존재하면, 세그먼트를 사용 : 오프셋 잘못된 방식으로 어드레싱 어드레스 0x8000:0x0000 세그먼트 값이 4 비트만큼 왼쪽으로 시프트 때문에, 선형 주소 0x80000로 해석되는 다음의 오프셋에 추가 .

이 문제를 해결하려면 메모리 덤프를보고 프로그램이 예상대로 작동하는지 확인해야합니다. 또는 디스크의 잘못된 섹터를로드하고 있습니다.

관련 문제