assemblykernelnasmintelx86-16

I have a problem with my kernel function "EXEC"


I'm writing a 16-bit x86 Assembly OS and I'm developing the program execution. The execution I've designed is different, because I want the kernel to execute the code (so it can have more control on what the program wants to do, so if it wants to overwrite the drive A: the user would be informed), not the CPU. So I'm writing the exec.asm file with the function that will read the program and execute the correspondent instruction. I'll leave you the source code before explaining my problem.

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 is running a program at 0x9014.

Today I've written the 0X7F instruction (for clearing the screen) in the exec.asm file. Now it works, but something changed in the 0X50, 0X51, 0X52 and 0X53 instructions (respectively to print a char, to print a string, a char pointed by BX and a null-terminating string pointed by BX). At the starting of these instructions you can see this snippet:

    PUSHA
    
    MOV DH, 0X03
    MOV DL, 0X00
    CALL _SETC
    
    POPA

which is used to set the cursor at the 4th line in the screen, but for some reason it's been bypassed since I've added the 0X7F instruction. Even if I store a big number in DH (the register that is used to store the row in which the cursor has to be moved), if called the printing function prints my char or my string at the 3rd line.

I use NASM to compile boot.asm and kernel.asm to two separate files, boot.bin and kernel.bin, and so I copy the two files into another one, main.bin, (using the Windows CMD command copy boot.bin/b+kernel.bin/b main.bin) which is the bootable one that I boot using Bochs Emulator 2.8.

I hope you could understand my problem (if you need more info tell me and I'll edit the post with the necessary info)!


Solution

  • You're executing command 0x53 right before command 0x7F.

    _0X7F:
        PUSHA
        MOV DH, 0X00
        MOV DL, 0X00
        CALL _SETC
        MOV BX, 0X19
        CALL CSCR
    

    Because of the number 0X19 (25 in decimal), the screen will scroll 1 line off at the top. The text that was printed at the 4th row (3) is now at the 3rd row (2).