我正在编写一个 16 位 x86 汇编操作系统,并且正在开发程序执行。我设计的执行是不同的,因为我希望内核执行代码(这样它可以对程序想要做什么有更多的控制,所以如果它想覆盖驱动器A:用户会被通知),不是CPU。所以我正在编写
exec.asm
文件,其中的函数将读取程序并执行相应的指令。在解释我的问题之前,我会将源代码留给您。
dload.asm
DLOAD:
PUSHA
MOV AH, 0X02
MOV AL, 0X04
MOV CH, 0X00
MOV CL, 0X02
MOV DH, 0X00
MOV DL, BL
MOV BX, 0X0000
MOV ES, BX
MOV BX, 0X7E00
INT 0X13
JC DERRR
DSUCC:
POPA
MOV AL, 0X00
RET
DERRR:
POPA
MOV AL, 0X01
RET
print.asm
PRINT_CHR:
PUSHA
MOV AH, 0X0E
MOV AL, [BX]
INT 0X10
POPA
RET
PRINT_STR:
PUSHA
MOV AH, 0X0E
PRINT_STR_LOOP:
MOV AL, [BX]
CMP AL, 0X00
JE END_PRINT_STR
INT 0X10
INC BX
JMP PRINT_STR_LOOP
END_PRINT_STR:
POPA
RET
screen.asm
SHOW_BASIC_SCREEN:
PUSHA
MOV AH, 0X0E
MOV BX, PNAME_OFFSET
MOV CX, 0X14
SHOW_PNAME:
MOV AL, [BX]
CMP CX, 0X00
JE SHOW_PNAME_END
INT 0X10
INC BX
DEC CX
JMP SHOW_PNAME
SHOW_PNAME_END:
MOV AL, '='
INT 0X10
INT 0X10
MOV CX, 0X12
AFTER_PNAME_SPACES:
MOV AL, ' '
CMP CX, 0X00
JE END_SPACING
INT 0X10
DEC CX
JMP AFTER_PNAME_SPACES
END_SPACING:
MOV AL, '='
INT 0X10
INT 0X10
MOV AL, ' '
INT 0X10
MOV AL, '}'
INT 0X10
MOV CX, 0X24
SHOW_INPUT_SPACE:
MOV AL, ' '
CMP CX, 0X00
JE END_INPUT_SPACE
INT 0X10
DEC CX
JMP SHOW_INPUT_SPACE
END_INPUT_SPACE:
MOV CX, 0X16
CLOSE_PNAME:
MOV AL, '='
CMP CX, 0X00
JE CLOSE_PNAME_END
INT 0X10
INC BX
DEC CX
JMP CLOSE_PNAME
CLOSE_PNAME_END:
MOV CX, 0X12
CLOSE_SPACES:
MOV AL, ' '
CMP CX, 0X00
JE CLOSE_SPACES_END
INT 0X10
DEC CX
JMP CLOSE_SPACES
CLOSE_SPACES_END:
MOV CX, 0X28
CLOSE_INPUT:
MOV AL, '='
CMP CX, 0X00
JE CLOSE_INPUT_END
INT 0X10
DEC CX
JMP CLOSE_INPUT
CLOSE_INPUT_END:
POPA
RET
PNAME_OFFSET EQU 0X9000
setc.asm
_SETC:
MOV AH, 0X02
MOV AL, 0X00
MOV BH, 0X00
INT 0X10
RET
cscr.asm
CSCR:
PUSHA
MOV CX, BX
MOV AH, 0X0E
CSCR_LOOP:
MOV AL, 0X0A
CMP CX, 0X00
JE CSCR_END
INT 0X10
DEC CX
JMP CSCR_LOOP
CSCR_END:
MOV AH, 0X02
MOV BH, 0X00
MOV DH, 0X00
MOV DL, 0X00
INT 0X10
POPA
RET
exec.asm
EXEC_INC:
INC BX
EXEC:
PUSHA
MOV BX, 0X02
CALL CSCR
CALL SHOW_BASIC_SCREEN
POPA
MOV AL, [BX]
CMP AL, 0X00
JE _0X00
CMP AL, 0X50
JE _0X50
CMP AL, 0X51
JE _0X51
CMP AL, 0X49
JE _0X49
CMP AL, 0X4A
JE _0X4A
CMP AL, 0X3C
JE _0X3C
CMP AL, 0X52
JE _0X52
CMP AL, 0X53
JE _0X53
CMP AL, 0X3E
JE _0X3E
CMP AL, 0X7F
JE _0X7F
JMP EXEC_ERR
_0X50:
PUSHA
MOV DH, 0X03
MOV DL, 0X00
CALL _SETC
POPA
INC BX
MOV AH, 0X0E
MOV AL, [BX]
INT 0X10
JMP EXEC_INC
_0X51:
PUSHA
MOV DH, 0X03
MOV DL, 0X00
CALL _SETC
POPA
INC BX
MOV AH, 0X0E
_0X51_LOOP:
MOV AL, [BX]
CMP AL, 0X00
JE EXEC_INC
INT 0X10
INC BX
JMP _0X51_LOOP
_0X49:
PUSHA
MOV DH, 0X00
MOV DL, 0X2D
CALL _SETC
MOV AH, 0X00
MOV BX, INPUT_ADDR
INT 0X16
MOV [BX], BYTE AL
POPA
JMP EXEC_INC
_0X4A:
PUSHA
MOV DH, 0X00
MOV DL, 0X2D
CALL _SETC
MOV BX, INPUT_ADDR
_0X4A_LOOP:
MOV AH, 0X00
INT 0X16
CMP AL, 0XD
JE _0X4A_END
CMP AL, 0X7F
JE _0X4A_DEL
MOV [BX], BYTE AL
MOV AH, 0X0E
INT 0X10
INC BX
JMP _0X4A_LOOP
_0X4A_DEL:
DEC BX
MOV [BX], BYTE 0X00
JMP _0X4A_LOOP
_0X4A_END:
MOV [BX], BYTE 0X00
POPA
JMP EXEC_INC
_0X3C:
INC BX
MOV AH, [BX]
INC BX
MOV AL, [BX]
PUSHA
MOV BX, PADDR
MOV [BX], BYTE AH
INC BX
MOV [BX], BYTE AL
POPA
JMP EXEC_INC
_0X52:
PUSHA
MOV DH, 0X03
MOV DL, 0X00
CALL _SETC
MOV BX, PADDR
MOV AH, [BX]
INC BX
MOV AL, [BX]
MOV BX, AX
MOV AH, 0X0E
MOV AL, [BX]
INT 0X10
POPA
JMP EXEC_INC
_0X53:
PUSHA
MOV DH, 0X03
MOV DL, 0X00
CALL _SETC
MOV BX, PADDR
MOV AH, [BX]
INC BX
MOV AL, [BX]
MOV BX, AX
MOV AH, 0X0E
_0X53_LOOP:
MOV AL, [BX]
CMP AL, 0X00
JE _0X53_END
INT 0X10
INC BX
JMP _0X53_LOOP
_0X53_END:
POPA
JMP EXEC_INC
_0X3E:
MOV BX, PADDR
MOV AH, [BX]
INC BX
MOV AL, [BX]
MOV BX, AX
ADD BX, 0X9000
JMP EXEC
_0X7F:
PUSHA
MOV DH, 0X00
MOV DL, 0X00
CALL _SETC
MOV BX, 0X19
CALL CSCR
POPA
JMP EXEC_INC
_0X00:
RET
EXEC_ERR:
MOV DH, 0X03
MOV DL, 0X00
CALL _SETC
MOV BX, EXEC_ERR_MSG
CALL PRINT_STR
EXEC_ERR_MSG:
DB "Error executing program.", 0X0A, 0X0D, "Unrecognized instruction code.", 0X0A, 0X0D, 0X00
PADDR EQU 0X8C00
boot.asm
[ORG 0X7C00]
MOV BP, 0XF000
MOV SP, BP
__MAIN:
MOV BX, DSKL_MSG
CALL PRINT_STR
MOV BL, DL
CALL DLOAD
CMP AL, 0X01
JE __ERR
MOV BX, DONE_DSKL_MSG
CALL PRINT_STR
MOV BX, KSTART_MSG
CALL PRINT_STR
JMP KOFFSET
__ERR:
MOV BX, ERRR_DSKL_MSG
CALL PRINT_STR
JMP __END
DSKL_MSG:
DB "Loading disk at 0x0000:0x7e00...", 0X0A, 0X0D, 0X00
DONE_DSKL_MSG:
DB "Disk loaded successfully at 0x0000:0x7e00.", 0X0A, 0X0D, 0X00
ERRR_DSKL_MSG:
DB "Fatal: unable to read disk. Cannot load kernel and boot the system.", 10, 13, 0
KSTART_MSG:
DB "Starting kernel... ", 0X0A, 0X0D, 0X00
KOFFSET EQU 0X7E00
%INCLUDE "print.asm"
%INCLUDE "dload.asm"
__END:
JMP $
TIMES 510 - ( $ - $$ ) DB 0X0
DW 0XAA55
kernel.asm
[ORG 0X7E00]
__KSTART:
MOV BX, KSTARTED_MSG
CALL PRINT_STR
MOV BX, 25
CALL CSCR
__MAIN:
MOV BX, 0X02
CALL CSCR
MOV [0X9000], BYTE 'P'
MOV [0X9001], BYTE 'A'
MOV [0X9002], BYTE 'R'
MOV [0X9003], BYTE 'R'
MOV [0X9004], BYTE 'O'
MOV [0X9005], BYTE 'T'
MOV [0X9006], BYTE ' '
MOV [0X9007], BYTE ' '
MOV [0X9008], BYTE ' '
MOV [0X9009], BYTE ' '
MOV [0X900A], BYTE ' '
MOV [0X900B], BYTE ' '
MOV [0X900C], BYTE ' '
MOV [0X900D], BYTE ' '
MOV [0X900E], BYTE ' '
MOV [0X901F], BYTE ' '
MOV [0X9010], BYTE ' '
MOV [0X9011], BYTE ' '
MOV [0X9012], BYTE ' '
MOV [0X9013], BYTE ' '
MOV [0X9014], BYTE 0X4A
MOV [0X9015], BYTE 0X3C
MOV [0X9016], BYTE 0X8A
MOV [0X9017], BYTE 0X00
MOV [0X9018], BYTE 0X53
MOV [0X9019], BYTE 0X7F
MOV [0X901A], BYTE 0X3C
MOV [0X901B], BYTE 0X00
MOV [0X901C], BYTE 0X14
MOV [0X901D], BYTE 0X3E
MOV [0X901E], BYTE 0X00
CALL SHOW_BASIC_SCREEN
MOV BX, 0X9014
CALL EXEC
KSTARTED_MSG:
DB "Kernel started successfully.", 0X0A, 0X0D, 0X00
INPUT_ADDR EQU 0X8A00
%INCLUDE "print.asm"
%INCLUDE "cscr.asm"
%INCLUDE "screen.asm"
%INCLUDE "setc.asm"
%INCLUDE "exec.asm"
JMP $
EXEC 正在 0x9014 处运行程序。
今天我在
exec.asm
文件中写入了0X7F指令(用于清除屏幕)。现在它可以工作了,但是 0X50、0X51、0X52 和 0X53 指令发生了一些变化(分别打印字符、打印字符串、BX 指向的字符和 BX 指向的空终止字符串)。在这些说明的开头,您可以看到以下片段:
PUSHA
MOV DH, 0X03
MOV DL, 0X00
CALL _SETC
POPA
用于将光标设置在屏幕的第4行,但由于某种原因,自从我添加了0X7F指令后,它就被绕过了。即使我在 DH 中存储一个大数字(用于存储光标必须在其中移动的行的寄存器),如果调用打印函数,也会在第三行打印我的字符或字符串。
我使用 NASM 将
boot.asm
和 kernel.asm
编译为两个单独的文件,boot.bin
和 kernel.bin
,因此我将这两个文件复制到另一个文件 main.bin
(使用 Windows CMD 命令copy boot.bin/b+kernel.bin/b main.bin
) )这是我使用 Bochs Emulator 2.8 启动的可启动启动项。
我希望您能理解我的问题(如果您需要更多信息,请告诉我,我将使用必要的信息编辑帖子)! 非常感谢。
您正在执行命令 0x53,就在命令 0x7F 之前。
_0X7F:
PUSHA
MOV DH, 0X00
MOV DL, 0X00
CALL _SETC
MOV BX, 0X19
CALL CSCR
由于数字 0X19(十进制 25),屏幕将在顶部滚动 1 行。打印在第 4 行 (3) 的文本现在位于第 3 行 (2)。