On 64-bit Ubuntu, I wrote a bootloader that loads a kernel, which provides an echo program (outputs whatever is inputted):
Bootloader Code:
[BITS 16]
org 0x7C00
bootdrive db 0
start:
mov [bootdrive], dl
mov ah, 0
int 13h
mov dx, 0
mov ah, 2
mov al, 0x10
mov dl, [bootdrive]
mov ch, 0
mov dh, 0
mov cl, 2
mov bx, 0
int 13h
jmp 0x1000:0000
times 510-($-$$) db 0
dw 0xAA55
Kernel Code:
[BITS 64]
call _stdin
jmp $
_stdin:
mov ah, 0
int 16h
mov ah, 0eh
mov bx, 0
int 10h
ret
int 16h/ah=0 takes input and puts the buffer into al. Then, I attempt to print al through int 10h/al=0eh, but it doesn't go through. I even tried putting
mov al, "!"
in between
mov ah, 0eh
and
mov bx, 0
but it doesn't seem to like the 16h interrupt. I also tried various other stdin commands using int 21h (ah = 8, ah = 1, ah = 0ah), but none of them was able to read a keystroke. I would type a key and press ENTER, but nothing would happen. More confusing was the fact that even the output command within int 21h (ah = 02h) did not print anything. I tried switching the kernel to real mode (32 bits) instead of long mode (64 bits), but int 21h still wouldn't work. To be clear, I want to be able to read keyboard input WITHOUT waiting for a return keystroke, so that I can alternate between calling the input interrupt and doing other processes. int 21h did not seem to work, not even in 32 bit mode, as well as int 16. The only interrupts that I have ever actually gotten to work were int 10h and int 13h (shown in the code), but the other interrupts don't work for some reason.
NOTE: I assembled the bootloader and kernel using nasm bootloader.asm -p kernel.asm to create a bin file named bootloader, and I used qemu-system-x86_64 to run the assembled bin file.
bootdrivevariable in the execution path B) I can't see to find whereesis set before the call toint 13h/ah=02hC) The kernel is assembled with 64-bit default operand size but you don't seem to switch to 64-bit mode D) You never "reset" the video mode, though this is not the issue here, I always felt safer doing it. - Margaret Bloombits 64only tells the assembler to generate 64-bit instruction encodings. It is up to the programmer to place the CPU in long mode before executing 64-bit code. Once in 64-bit protected mode you can't directly access the BIOS functions anymore either (without switching back to real mode first) - Michael Petchbootdrive db 0will be executed as an instruction potentially causing issue. Place your variables after the last instruction of your bootloader and beforetimes 510-($-$$) db 0.bootdrive db 0should be placed afterjmp 0x1000:0000and beforetimes 510-($-$$) db 0in your case - Michael Petchint 21his not available in a bootloader.int 21his a DOS interrupt. DOS isn't available at the stage a bootloader starts, just the BIOS and direct hardware access. - Michael Petch