2017-11-17 3 views
1

어셈블리에서 기본 부트 로더를 만들었지 만 실제로 커널로 점프하지는 않습니다. 그냥 "부팅 중 ..."이라고 말합니다. 나는 그것이 잘못된 장소로 점프하는 것처럼 내가 만든 바보 같은 실수 일 것이라고 확신한다. "부팅 중 ...로드 됨!"과 같은 출력이 표시되어야합니다. 또한 그것을로드하기 전에 es를 0으로 설정하려고했지만 작동하지 않습니다. 내 코드는 다음과 같습니다.어셈블리 부트 로더가 커널로 점프하지 않습니다

mov ax, 9ch 
mov ss, ax 
mov sp, 4096d 
mov ax, 7c0h 
mov ds, ax 
mov es, ax 

xor ah, ah 
int 13h 

clc 

mov si, msg2 
call print 

mov ah, 02h 
xor ax, ax 
mov es, ax 
mov bx, 0x7E00 
mov al, 1h 
mov ch, 0 
mov cl, 2h 
mov dh, 0 
int 13h 

jc error 

jmp 0x7E00 

mov si, msg3 
call print 

error: 
mov si, msg 
call print 
hlt 

print: 
lodsb 
cmp al, 0 
jz done 
mov ah, 0eh 
int 10h 
jmp print 
done: 
ret 

msg db "An error occured!!", 0 
msg2 db "Booting...", 0 
msg3 db "Did not jump to kernel correctly!" 

times 510-($-$$) db 0 
dw 0xAA55 

mov si, msgloaded 
call printl 
jmp $ 

printl: 
lodsb 
cmp al, 0 
jz donel 
mov ah, 0eh 
int 10h 
jmp print 
donel: 
ret 

msgloaded db "Loaded!", 0 

times 0x400-($-$$) db 0 

모든 도움을 받으실 수 있습니다. 나를 도울 수있는 사람은 누구에게나 신용 할 것입니다. 감사!

+0

커널로 점프하지 않았을 수도 있습니다. – Jester

+0

죄송합니다. 상자에 복사 할 때 실수로 삭제 했어야합니다. 죄송합니다. – programmer

+0

또한 'int 13h' 호출은 잘못된 위치에 있습니다 (인수를 설정하기도 전에 ???) ** 그리고 ** 잘못된 위치에 데이터를로드하고 있습니다. – Jester

답변

3

고급 언어에는 프로그래머가 의도 한 구조 루프에 대한 많은 단서, 변수 이름 선택 방법,/enums 정의 등이 있습니다. 주석없이 유지 보수 가능한 코드를 작성하는 것은 쉽습니다.

어셈블리 언어에는 잘 선택되지 않은 변수 이름과 변수 유형이 없습니다 (예 : ax은 문자열이나 기린의 높이 또는 ...에 대한 포인터 인 경우 독자에게 알려주지 않음), 지침에 종종 (예 : lea은 상수로 곱하기 위해 사용될 수 있고 유효 주소를로드하는 데 사용되지 않을 수 있습니다.) 제어 흐름은 훨씬 더 유연합니다 (예 : do(condition1) { } while(condition2)과 같이 완벽 함) goto (jmpjc) 많이 사용됩니다.

이런 이유로 잘 쓰여진/유지 보수 가능한 어셈블리 언어는 많은 주석을 사용합니다. 좀 더 구체적으로 말하자면, 오른쪽에있는 의견을 사용하여 의도를 설명하십시오. 이를 통해 주석을 읽음으로써 의도가 올바른지 확인한 다음 각 줄의 명령어를 주석과 비교하여 의도가 올바르게 구현되었는지 확인할 수 있습니다. 버그를 피하는 것이 훨씬 쉬우 며 버그를 찾기가 훨씬 쉽습니다. 여기

;Memory Layout 
; 
; 0x009C:0x1000 = 0x000019C0 = stack top 
; 0x07C0:0x0000 = 0x00007C00 = load address 
; 0x0000:0x7E00 = 0x00007E00 = kernel address 

%define STACK_SEGMENT  0x009C 
%define STACK_TOP_OFFSET 0x1000 
%define LOAD_SEGMENT  0x07C0 
%define KERNEL_SEGMENT  0x0000 
%define KERNEL_OFFSET  0x7E00 

;_______________________________________________ 

;Entry point 
; 
;Input 
; dl = BIOS boot device number 

    mov ax, STACK_SEGMENT 
    mov ss, ax 
    mov sp, STACK_TOP_OFFSET 
    mov ax, LOAD_SEGMENT 
    mov ds, ax 
    mov es, ax 

;Reset disk system 
; 
;Note: This should be completely unnecessary. We know the BIOS 
;  disk services are working correctly and don't need 
;  to be reset because the BIOS just used it successfully 
;  to load this code into memory. 

    xor ah, ah   ;ah = BIOS "reset disk system" function number 
    int 13h    ;Call BIOS disk services 
    clc     ;Unnecessary 

;Display welcome message 

    mov si, msg2 
    call print 

;Load kernel from disk 
; dl = BIOS boot device number 

    mov ah, 02h   ;ah = BIOS "read sectors" function number 
    xor ax, ax   ;ax = KERNEL_SEGMENT 
    mov es, ax 
    mov bx, KERNEL_OFFSET ;es:bx = address to load kernel 
    mov al, 1h   ;al = number of sectors to read 
    mov ch, 0    ;ch = cylinder number for first sector 
    mov cl, 2h   ;cl = sector number for first sector 
    mov dh, 0    ;dh = head number for first sector 
    int 13h    ;Call BIOS disk services 

    jc error    ;Handle error if there was one 

;Pass control to "kernel" 

    jmp KERNEL_SEGMENT:KERNEL_OFFSET 

분명 버그 만드는 부분 :

여기 의견 코드의 상반기의 제대로 코드를 주석 경우 기본적으로

      ;ah = BIOS "read sectors" function number 
          ;ax = KERNEL_SEGMENT 

을, 당신은했습니다 것 KERNEL_SEGMENTax에로드하면 BIOS 기능 번호 (가장 높은 8 비트 인)를 덮어 씁니다. 이로 인해이 코드가 BIOS를 "디스크 시스템 재설정"기능을 호출하고 디스크에서 아무것도로드하지 않습니다. 나중에 커널을로드해야하는 위치로 점프 할 때, 사용되지 않았기 때문에 그 메모리는 여전히 0으로 채워지지만, 0으로 가득 찬 메모리는 CPU에 의해 add 명령으로 디코딩됩니다. 그래서 CPU는 기쁜 듯이 연령대에 따라 add 지침을 실행합니다.

참고 : 다른 (관련없는) 버그가 있습니다. 문자열을 인쇄하는 코드는 방향 플래그에 따라 lodsb을 사용합니다. 그러나 cld 명령을 사용하여 방향 플래그를 설정하지 마십시오. BIOS가 (정의되지 않은) 상태에 따라 BIOS가이 플래그를 남겨두면 쓰레기를 대신 인쇄 할 수 있습니다.

+0

'0x07C0 : 0x0000 = 0x00007C00 = 로드 주소 '-> 아니요, BIOS에 따라 다릅니다. 그리고'0000 : 7C00'은 훨씬 더 보편적이지만, 충분히 견고한 부트 로더는 항상'cs : ip'를 예상 상태로 "정상화"하기 위해 먼 점프부터 시작합니다. – Ped7g

+0

그렇다면 내가해야 할 일은 무엇일까요? 나는 int 13h 호출 전에 직접 설정을 시도했지만 심지어 작동하지 않습니다. – programmer

+0

@ Ped7g : 예, 아니요. 이 코드의 어떤 것도 실제로'CS'에 의존하지 않습니다 (그리고 BIOS가'0x0000 : 0x7C00'을 대신 사용한다면 잘 작동합니다); 그 주석 (및'% define')은 데이터 (예 :'DS',로드되고 문자열 인쇄에 사용됨)에 사용 된 의도를 문서화합니다. 'jmp LOAD_SEGMENT : start'는 좋을 것입니다. (그리고 미래의 버그는 피할 수 있습니다.) – Brendan

관련 문제