2014-04-09 1 views
1

어셈블리 프로그래밍에서 3-4 일 전입니다. 비디오 메모리에 문자열을 인쇄하고 qemu를 실행하려고합니다. 이 프로그램이 Hallo 세계를 인쇄 할 것으로 예상했습니다. 그러나 아무것도 인쇄하지 않습니다. qemu 창에 "하드 디스크에서 부팅 중 ..."다른 내용이 없습니다.비디오 메모리에 부트 로더 인쇄 0xb8000

부트 로더에서 16 비트 만 허용됩니까? 그렇다면 어떻게하면 MMIO를 할 수 있습니까? I는 실제 페이지 32 16 비트의 실제 모드 대 http://www.cs.bham.ac.uk/~exr/lectures/opsys/10_11/lectures/os-dev.pdf

[bits 32] 
[org 0x7c00] 

loop: 
    mov edx, 0xb8000 
    mov ah, 0x0f 

    mov ebx, message 
    mov ecx, 0x0 
    call draw_string 

    ;jmp self_loop 
    ;jmp loop 

self_loop: 
    jmp self_loop 

; take the stream begining from ebx 
draw_string: 
    mov al, [ebx] 
    mov ah, 0x0f 

    mov [edx], ax 
    add ebx, 1 
    add edx, 2 

    cmp al, 0 

    jne draw_string 
    ret 

message: 
    db 'Hallo World', 0x0 

times 510 -($ - $$) db 0 ; When compiled , our program must fit into 512 bytes , 
       ; with the last two bytes being the magic number , 
       ; so here, tell our assembly compiler to pad out our 
       ; program with enough zero bytes (db 0) to bring us to the 
       ; 510th byte. 
dw 0xAA55   ; Last two bytes (one word) form the magic number , 
       ; so BIOS knows we are a boot sector. 
+0

이 작업을 수행 할 때는 보호 모드가 아닙니다. 그렇습니까? 세그먼트 화 된 주소 지정을 사용해야합니다. – Michael

+1

보호 모드는 어떻게 지정합니까? 세그먼트 주소 지정은 어떻게 지정합니까? 나는'nasm -f bin file.asm -o file.bin'을 컴파일하고'qemu-system-i386 file.bin'을 가지고 컴파일하고있다. –

답변

1

예 [32 비트 보호 모드 입력] 기본 세그먼트 크기 64 킬로바이트 제한 CPU 시작에서 주소별로 분류를 수행 하였다. 리얼 모드에서는 32 비트 오프셋 레지스터 (80386+)를 사용할 수 있지만 오프셋 주소는 세그먼트 한계의 64KB 크기를 가리켜 야하며 64KB 세그먼트 크기 외부의 주소를 가리킬 수 없습니다 . (0 ~ FFFF 사이의 오프셋에 액세스하기 위해 32 비트 오프셋 레지스터가 필요하지 않으므로이 예제에서는 16 비트 오프셋 레지스터를 사용합니다.) 64KB 이외의 다른 영역에 액세스하려면 다른 세그먼트 레지스터를 사용하거나 다른 세그먼트 주소를 세그먼트 레지스터에 저장할 수 있습니다. 헬로 세계 메시지의 바이트 코드 세그먼트에 배치되어 있기 때문에

...

, 우리는 메시지의 각 바이트를 얻을 수 있도록, 데이터 세그먼트 레지스터에 동일한 세그먼트 주소를 사용하고 싶습니다.

이제 우리는 텍스트 모드 비디오 버퍼의 세그먼트 주소를 여분의 세그먼트 레지스터에 저장합니다.

mov ax,0xb800 ; = this is a segment address and not a linear offset address 
mov es,ax 

lea bx,message ; Now we get the source address in BX 
mov di,0x0  ; and the target address for output (upper left corner) in DI 

call draw_string 

self_loop: 
jmp self_loop 

; take the stream begining from DS:bx 
draw_string: 
mov al,[bx] ; load a byte from the address of DS:BX 
mov ah,0x0f 

mov es:[di],ax ; store a word to the address of ES:DI 
add bx,1 
add di,2  ; increasing the target offset address 

cmp al,0 
jne draw_string 
ret