我使用 GNU 汇编器和 AT&T 语法编写了我的第一个引导加载程序。假设将 hello world
打印到屏幕上,然后通知用户按任意键将导致重新启动。只有按下某个键后才会启动重新启动。我的引导加载程序代码不等待按键,并在打印信息后自动重新启动。为什么此代码不等待击键,如何修复它?
我的引导扇区代码:
#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
最佳答案
Int 0x16 AH=0将等待击键:
KEYBOARD - GET KEYSTROKE
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作为第一条指令如果您没有 BPB。
您可能在表现出所需行为的模拟器下运行,但如果您将此引导加载程序移动到其他环境(甚至其他模拟器),您可能会发现它无法按预期工作。
<小时/>最后,您手动编码长跳转以进行重新启动:
.byte 0x0ea
.word 0x0000
.word 0xffff
尽管您可能必须在某些旧版本的 MASM 或 TASM 中执行此操作,但具有 AT&T 语法的 GNU 汇编器支持这样做:
jmp $0xffff,$0x0000
关于assembly - INT 16h/AH=0h 不等待引导加载程序中的按键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37101521/