我正在编写一个 16 位 x86 汇编操作系统,并且正在开发程序执行。我设计的执行有所不同,因为我希望内核执行代码(这样它就可以更好地控制程序要做什么,因此如果它想覆盖驱动器 A:用户会得到通知),而不是 CPU。所以我正在编写一个文件,exec.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
打印.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
屏幕文件
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:
MOV AH, 0X02
MOV AL, 0X00
MOV BH, 0X00
INT 0X10
RET
汇编语言
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_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
启动文件
[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
内核汇编
[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 的程序。
今天我在文件中写入了 0X7F 指令(用于清除屏幕)exec.asm
。现在它可以工作了,但 0X50、0X51、0X52 和 0X53 指令中发生了一些变化(分别用于打印字符、打印字符串、BX 指向的字符和 BX 指向的以空字符结尾的字符串)。在这些指令的开头,您可以看到以下代码片段:
PUSHA
MOV DH, 0X03
MOV DL, 0X00
CALL _SETC
POPA
它用于将光标设置在屏幕的第 4 行,但由于某种原因,自从我添加了 0X7F 指令后,它就被绕过了。即使我在 DH(用于存储光标必须移动到的行的寄存器)中存储了一个大数字,如果调用打印函数,它会在第 3 行打印我的字符或字符串。
我使用 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 启动的可启动文件。
我希望你能理解我的问题(如果你需要更多信息请告诉我,我会编辑帖子并添加必要的信息)!
您正在执行命令 0x7F之前命令 0x53。
由于数字 0X19(十进制为 25),屏幕将在顶部滚动一行。打印在第 4 行(3)的文本现在位于第 3 行(2)。