我试图使一个非常简单的启动程序,但我有问题调试它。我正在使用QEMU并与GDB连接,像这样:
(gdb) set architecture i8086
(gdb) target remote localhost:1234
(gdb) break *0x7C00
(gdb) layout asm
(gdb) continue
…它工作得很好,我可以得到我的代码的前几个指令。然而,只要我在一个特定的int
指令上执行si
或ni
,这种模式就会出现在GDB汇编视图中。
0x8669 add %al,(%bx,%si) │
0x866b add %al,(%bx,%si) │
0x866d add %al,(%bx,%si) │
<ad nauseam>
这似乎没有停止,或返回到我期望的地方。下面是我的汇编代码:
stage1。h2 S #include "stage1.h"
.text
.code16
.org STAGE1_START
.globl _start
_start:
JMP main
NOP
write:
LODSB
OR %al, %al
JZ write_exit
MOV $0xE, %ah
MOV $0x9, %bx
INT $0x10
JMP write
write_exit:
RET
video_setup:
MOV $0x0, %ah
MOV $0x3, %al
INT $0x10 /* This causes the problem. */
RET
LoadMsg: .asciz "Loading second stage..."
BootDrive: .byte
main:
MOV %dl, STAGE1_ABS_POS(BootDrive)
CALL video_setup
LEA STAGE1_ABS_POS(LoadMsg), %si
CALL write
HLT
/* Fill file to 512 bytes, regardless. */
.fill STAGE1_BOOTLOADER_SIZE - (. - _start)
/* BIOS magic. */
.word STAGE1_BOOTLOADER_SIG
stage1.h
#ifndef STAGE_1_H
#define STAGE_1_H
#define STAGE1_START 0x0
#define STAGE1_BOOTLOADER_OFFSET 0x7C00
#define STAGE1_BOOTLOADER_SIG 0xAA55
#define STAGE1_BOOTLOADER_SIZE 0x1FE
#define STAGE1_ABS_POS(X) (X-_start+STAGE1_BOOTLOADER_OFFSET)
#endif
#include "stage1.h"
.text
.code16
.org STAGE1_START
.globl _start
_start:
JMP main
NOP
write:
LODSB
OR %al, %al
JZ write_exit
MOV $0xE, %ah
MOV $0x9, %bx
INT $0x10
JMP write
write_exit:
RET
video_setup:
MOV $0x0, %ah
MOV $0x3, %al
INT $0x10 /* This causes the problem. */
RET
LoadMsg: .asciz "Loading second stage..."
BootDrive: .byte
main:
MOV %dl, STAGE1_ABS_POS(BootDrive)
CALL video_setup
LEA STAGE1_ABS_POS(LoadMsg), %si
CALL write
HLT
/* Fill file to 512 bytes, regardless. */
.fill STAGE1_BOOTLOADER_SIZE - (. - _start)
/* BIOS magic. */
.word STAGE1_BOOTLOADER_SIG
#ifndef STAGE_1_H
#define STAGE_1_H
#define STAGE1_START 0x0
#define STAGE1_BOOTLOADER_OFFSET 0x7C00
#define STAGE1_BOOTLOADER_SIG 0xAA55
#define STAGE1_BOOTLOADER_SIZE 0x1FE
#define STAGE1_ABS_POS(X) (X-_start+STAGE1_BOOTLOADER_OFFSET)
#endif
我知道代码不会在内存中随机跳转,因为当我在QEMU中没有调试选项的情况下运行它时,程序会正常工作。
我做错了什么?对我的代码的批评也非常感谢。
我不知道确切的原因,但事实证明,中断最终混淆了调试器或QEMU的调试模式(或者我做错了什么,但我不确定是什么)。
无论如何,为了解决这个问题,我只是在我希望调试的下一个指令处放置断点,然后在中断指令之前放置continue
。
谢谢你的帮助,评论者。: -)