2016-05-08 13 views
4

Я написал свой первый загрузчик с помощью GNU Assembler с AT & T синтаксисом. Предположим, чтобы напечатать hello world на экране, затем сообщите пользователю, что нажатие любой клавиши приведет к перезагрузке. Только после нажатия клавиши происходит перезагрузка, которая должна быть инициирована. Мой код загрузчика не ждет ключа и автоматически перезагружается после печати информации. Почему этот код не ждет нажатия клавиши, и как я могу его исправить?INT 16h/AH = 0h не ждет нажатия клавиши в моем загрузчике

Мой код загрузочного сектора:

#generate 16-bit code 
.code16 

#hint the assembler that here is the executable code located 
.text 
.globl _start; 
#boot code entry 
_start: 
    jmp _boot       #jump to boot code 
    welcome: .asciz "Hello, World\n\r" #here we define the string 
    AnyKey: .asciz "Press any key to reboot...\n\r" 
.macro mWriteString str    #macro which calls a function to print a string 
     leaw \str, %si 
     call .writeStringIn 
.endm 

#function to print the string 
.writeStringIn: 
     lodsb 
     orb %al, %al 
     jz .writeStringOut 
     movb $0x0e, %ah 
     int $0x10 
     jmp .writeStringIn 
.writeStringOut: 
ret 
#Gets the pressed key 
.GetPressedKey: 
mov 0, %ah 
int $0x16 #BIOS Keyboard Service 
ret 

.Reboot: 
    mWriteString AnyKey 
    call .GetPressedKey 

#Sends us to the end of the memory 
#causing reboot 
.byte 0x0ea 
.word 0x0000 
.word 0xffff 
_boot: 
    mWriteString welcome 
    call .Reboot 
    #move to 510th byte from the start and append boot signature 
    . = _start + 510 
    .byte 0x55 
    .byte 0xaa 
+1

спасибо :) он работает сейчас –

ответ

3

Int 0x16 AH=0 будет ждать нажатия клавиши:

КЛАВИАТУРЫ - GET НАЖАТИЕ КЛАВИШИ

AH = 00h 

Return: 
AH = BIOS scan code 
AL = ASCII character 

Вы имели право идею с этим:

mov 0, %ah 
int $0x16 #BIOS Keyboard Service 
ret 

Проблема в том, что mov 0, %ah рассматривает 0 как операнд памяти. В этом случае это будет то же самое, что перемещение значения байта в DS: [0] в AH. Вы просто хотите перенести ближайшее (постоянное) значение 0 на AH. В AT & T синтаксис немедленных значений предшествует знаку доллара $. Если значение не имеет префикса с помощью ассемблера GNU $, предполагается, что это ссылка на память. Код должен быть:

mov $0, %ah 
int $0x16 #BIOS Keyboard Service 
ret 

В качестве альтернативы вы могли бы обнулить AH с:

xor %ah, %ah 

Ваш код сделать некоторые предположения относительно значения регистра DS, когда ваш загрузочный загрузчик, и он не устанавливает свой собственный стек. Для некоторых хороших практик написания загрузчика, который будет работать с большим количеством эмуляторов и реального оборудования, вы можете взглянуть на некоторые из моих General Bootloader Tips, приведенные в предыдущем ответе Stackoverflow.

Кроме того, в вашем случае я мог бы переместить ваши данные после кода и удалить JMP в начале, так как вы не используете BIOS Parameter Block. Некоторые BIOS будут искать JMP в начале загрузочного сектора и предположить, что у вас есть BPB и может фактически перезаписать ваш код, думая, что он заполняет значения структуры данных. Лучшим способом избежать этой ситуации является простое отсутствие JMP в качестве первой инструкции IF у вас нет BPB.

Скорее всего, вы работаете под эмулятором, который проявляет поведение, которое вам нужно, но если вы должны переместить этот загрузчик в другие среды (и даже другие эмуляторы), вы можете обнаружить, что он работает не так, как ожидалось.


В конце концов вы вручную кодировать длинный прыжок, чтобы сделать перезагрузку:

.byte 0x0ea 
.word 0x0000 
.word 0xffff 

Хотя вы, возможно, должны были сделать это в некоторых старых версиях MASM или TASM, GNU ассемблер с AT & T поддерживает синтаксис таким образом:

jmp $0xffff,$0x0000