C Inline Asm Int 0x10
Okay after some helpful comments, I may just go with full assembly. Something like
Print:
push %ax
movb $0x0E, %ah # Set interrupt code
movb $0x00, %bh # Set page #
.loop:
lodsb # Load next char
test %al, %al # Check for \0
je .done
int $0x10 # Call interrupt
jmp .loop
.done:
pop %ax
ret
That should be 16-bit real mode compatible and can be assembled with GAS, which, as I understand it, works better than GCC for compiling 16-bit programs.
two int 0x10 command,one in bios, one in processor
In X86 architecture, interrupt handlers are defined in the Interrupt descriptor table (IDT).
In read mode, The IDT consists of 256 four-byte real mode pointers. When system startup, BIOS will initialize this IDT to provide some basic service for real mode programs (for example DOS code / OS boot code). The handlers are all defined in BIOS.
Later, the OS boot code may switch the processor into protected mode and load its new IDT. This time the IDT is an array of 8-byte descriptors stored in memory. From this point, OS start to handle interrupts instead of BIOS.
So there is no contradictory since the first int 0x10 is used to invoke BIOS service in real mode and then its handling is passed to OS to handle exceptions in protected mode.
Interrupt 10h not working
BIOS interrupts are 16-bit code. Your OS has put the CPU in 32-bit protected mode. The hardware will allow a switch back to 16-bit real mode (there are hoops to jump through) but the OS won't allow it. Wouldn't be very "protected" if it did. It is "protected" from US, my friend!
I think what you probably want to look into is "vt100" terminal emulation. By rights, a "robust" program would consult the "termcaps" file to make sure vt100 emulation is available before attempting to use it. My experience is that it's "usually" available on a "desktop Linux" box, so I just ASSume it's there. Worst that can happen (I think) is garbage on the screen if we ASSume wrong.
This example doesn't do exactly what you want. It saves the current cursor position (lord knows where), moves the cursor to a new position, prints a message, and goes back to the original cursor position. You'll need to look up the "home cursor" command ("ESC [h"? lookitup). Just write it to stdout, same as "hello world". You can get colors and stuff, too.
; nasm -f elf32 mygem.asm
; ld -o mygem mygem.o -melf_i386
global _start
section .data
savecursor db 1Bh, '[s'
.len equ $ - savecursor
unsavecursor db 1Bh, '[u'
.len equ $ - unsavecursor
getcursor db 1Bh, '[6n'
.len equ $ - getcursor
setcursor db 1Bh, '[10;20H'
.len equ $ - setcursor
msg db "Hello, new cursor position!"
.len equ $ - msg
section .text
_start:
mov ecx, savecursor
mov edx, savecursor.len
call write_stdout
mov ecx, setcursor
mov edx, setcursor.len
call write_stdout
mov ecx, msg
mov edx, msg.len
call write_stdout
mov ecx, unsavecursor
mov edx, unsavecursor.len
call write_stdout
exit:
mov eax, 1
xor ebx, ebx
int 80h
;------------------------
write_stdout:
push eax
push ebx
mov eax, 4
mov ebx, 1
int 80h
pop ebx
pop eax
ret
;---------------------
Int 10H not working in QEMU
It appears that your linker script was written for an environment where a protected mode kernel would be loaded at 0x00100000. This is common for bootloaders conforming to the multiboot specification. Real mode bootloader like yours will be read from the first 512 bytes of the disk and placed at 0x7c00 in memory. You'll need a linker script that uses an origin point of 0x7c00. You can also use the linker script to output the boot disk signature 0xAA55.
A basic bootloader linker script could look something like this link.ld
:
OUTPUT_FORMAT("binary");
ENTRY(start);
SECTIONS
{
. = 0x7C00;
.text : AT(0x7C00) {
*(.text);
}
.data : SUBALIGN(0) {
*(.data);
*(.rodata);
}
.bss : SUBALIGN(4) {
__bss_start = .;
*(COMMON);
*(.bss)
. = ALIGN(4);
__bss_end = .;
}
__bss_sizel = SIZEOF(.bss)>>2;
__bss_sizeb = SIZEOF(.bss);
/* Boot signature */
.sig : AT(0x7DFE) {
SHORT(0xaa55);
}
}
Your boot.s
is not being told to generate 16-bit code. You can place the directive .code16
at the top of your assembly file to force it to generate 16-bit instructions. You will also have to amend your GCC command to compile as 16-bit code, and the linker will need the -melf_i386
option.
Your bootloader code should really set the DS register as well as the stack. Since the linker script assumes code is located at memory location 0x07c00 we'll need to set DS to zero. In segmented model a physical address = (segment<<4)+offset . DS set to 0, and an origin (base offset) of 0x7c00 would map to (0<<4)+0x7c00 = physical address 0x07c00 which is where our bootloader is loaded by the BIOS.
I wrote an answer with some general bootloader tip that may be of some value.
Cleaned up boot.s
could look like:
#
# boot.s
#
.code16
.section .text
.globl start
start:
//setup stack
mov $0x7c0, %ax
mov %ax, %ss
mov $512, %sp
xor %ax, %ax # AX = 0
mov %ax, %ds # Set DS = 0 since origin point is 0x7c00
//setup video
xor %ax, %ax # Zero 16-bit AX register (includes AL and AH)
//mov $0x0, %ax # Works but is not preferred for zeroing a reg
int $0x10
//print a character say 'm'
mov $'m', %al
mov $0x0E, %ah
int $0x10
1:
jmp 1b
To assemble, link and generate a disk image you could use:
gcc -c boot.s -m16
ld -melf_i386 -T link.ld boot.o -o b.bin -nostdlib --nmagic
dd if=b.bin of=HD.img conv=notrunc
You could then run it using the image as a floppy:
qemu-system-i386 -fda HD.img
Or as a hard drive image using:
qemu-system-i386 -hda HD.img
Related Topics
Linking with 32Bit Libraries Under Linux 64Bit
How to Ensure Data Reaches Storage, Bypassing Memory/Cache/Buffered-Io
Vue Npm Run Serve Failed to Load Resource: Net::Err_Content_Length_Mismatch
How to Reserve Ip When Provisioning Azure Vm (Resource Manager)
What Happens When I Sudo Bash -C
How to Two Mmap on Same /Dev File
Kaldi Toolkit Installation Error on Ubuntu 16.04
Tcp Keepalive - Protocol Not Available
Linux History of All Commands Executed During Whole Day, Everyday
How to Simulate a Usb Printer to Lpt on Linux
Does Routing Affect a Socket with a Bound Source Address
How to Print Multiple Variables Using Printf
Restart Service from Cgi Script
How to Create a Folder with a Folder Name Containing Spaces in Linux
Can't Load Mod_Wsgi Compiled for Python 3
Gitlab Ce Doesn't Add a Public Key to Authorized_Keys