Please, help me linking my .asm and .c!
Posted: Fri May 14, 2021 9:38 am
Hello everyone!
I am a fullstack dev taking his first steps in kernel programming. Please don't laugh at me for being a total n00b.
I've written an .asm that enables protected mode, and (supposedly) jumps to the address of a kernel. Yet I literally have no idea how I can link the two files. I've tried several solutions I found on google, yet no one would work -not running in qemu, in particular. I only either encounter a "not a bootable disk" message, or it would just do nothing after enabling A20.
I would really appreciate it if someone gave me a useful guide for linkers (Google didn't, so far).
If someone is willing to give me a ready solution as well, here are the codes:
stage0.asm:
hello.c (version 1):
hello.c (version 2):
Thank you in advance!
I am a fullstack dev taking his first steps in kernel programming. Please don't laugh at me for being a total n00b.
I've written an .asm that enables protected mode, and (supposedly) jumps to the address of a kernel. Yet I literally have no idea how I can link the two files. I've tried several solutions I found on google, yet no one would work -not running in qemu, in particular. I only either encounter a "not a bootable disk" message, or it would just do nothing after enabling A20.
I would really appreciate it if someone gave me a useful guide for linkers (Google didn't, so far).
If someone is willing to give me a ready solution as well, here are the codes:
stage0.asm:
Code: Select all
org 0x7c00 ;endast för -f bin
[BITS 16] ; den tha doulepsei alliws.
_start:
cli
cld ; clear direction flags
mov ax, 03h ;Clear the screen
int 10h ; BIOS call for clearing
xor ax,ax
;mov cs, ax ;it fucks the printing up!!!
mov ds, ax
mov es, ax
mov ss, ax
; mov sp, 0x8000
mov ah, 0x0e
mov si, realModeMsg
call printmsg
call a20_gate_fast
hlt
a20_gate_fast:
xor ax,ax
;There is no guarantee that this works on a system! It works in most cases,
in al, 0x92 ;but not always. TODO: Implement at least one more algorithm enabling A20
or al, 2
out 0x92, al
call check_a20
xchg bx, bx
cmp ax, 0
jne enable_A20__done ;jump if A20 enabled
hlt
enable_A20__done:
;xor ax,ax
mov ah, 0x0e
mov si, A20sucess
;mov al, [si]
jmp printmsg
jmp load_gdt
;http://www.independent-software.com/operating-system-development-enabling-a20-line.html
; https://stackoverflow.com/questions/52668637/is-my-understanding-of-the-a20-line-check-code-correct
check_a20:
pushf ;Backup the current flags onto the stack
;Backup the below registers onto the stack
push ds ;|
push es ;|
push di ;|
push si ;-----
cli ;Disable interupts
xor ax, ax ; ax = 0
mov es, ax ;es = ax
not ax ; ax = 0xFFFF
mov ds, ax ; ds = ax
mov di, 0x0500 ;Boot signature part one (0x55)
mov si, 0x0510 ;Boot signature part two (0xAA)
mov al, byte [es:di] ;al = value at AA:55
push ax ;Backup ax register onto the stack
mov al, byte [ds:si] ;al = value at 55:AA
push ax ;Backup al onto the stack
mov byte [es:di], 0x00 ;Memory location AA:55 = 0
mov byte [ds:si], 0xFF ;Memory location at 55:AA = 0xFF
cmp byte [es:di], 0xFF ;Does value at AA:55 = 0xFF? If so, this means A20 is disabled
pop ax ;Restore saved ax register
mov byte [ds:si], al ;Set 55:AA to al
pop ax ;Restore ax register
mov byte [es:di], al ;set AA:55 to al
mov ax, 0 ;Return status of this function = 0 (Disabled)
je check_a20__exit ;A20 is disabled. Go to check_a20__exit
mov ax, 1 ;Return status of this function = 1 (Enabled)
jmp check_a20__exit
ret
check_a20__exit:
;Backup registers
pop si
pop di
pop es
pop ds
popf ;Backup flags
ret ;Return
;FOUND ON OSDev.org. Similarly implemented on simple-x86-bootloader
load_gdt:
mov ax, gdtend
mov bx, gdt
sub ax, bx ; compute GDT's limit
mov WORD [gdtptr], ax
xor eax, eax ; compute linear of GDT
mov ax, ds
shl eax, 4
xor ebx, ebx
mov bx, gdt
add eax, ebx
mov DWORD [gdtptr + 2], eax
jmp protected_mode
protected_mode:
cli
lgdt [gdtptr] ; load gdt
mov eax, cr0
or ax, 1
mov cr0, eax
jmp 0x08:init_pm
second_msg:
mov si, realModeMsgg
call printmsg
;;functions for general use
printmsg:
mov al, [si]
add si, 1
cmp al, 0xa
jne print_interrupt
ret
; alternative way:
;lodsb
;or al,al
;jz print_interrupt
print_interrupt:
int 0x10
jmp printmsg
[bits 32]
init_pm:
mov ax, 0x10
mov ds, ax
mov ss, ax
mov esp, 0x090000 ; set up stack pointer
mov byte [0xB8000], 88
mov byte [0xB8000+1], 0x1B
call dword 0x08:0x01000 ; go to C code
mov byte [0xB8000+4], 89
mov byte [0xB8000+5], 0x1B
jmp $
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[bits 16]
.data
realModeMsg db 'Real mode...', 0xa
realModeMsgg db 'EWWWWWWWWWWWWWWWWWWW', 0xa
A20errorMsg db 'Error enabling A20', 0xa
A20sucess db 'A20 successfully enabled!', 0xa
gdt: ;gdt based on simple-x86-bootloader
db 0, 0, 0, 0, 0, 0, 0, 0
gdt_cs: ; flat model
db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10011011b, 11011111b, 0x0
gdt_ds: ; flat model
db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10010011b, 11011111b, 0x0
gdtend:
;---------------------------------------------------------
gdtptr:
dw 0 ; limite
dd 0 ; base
;--------------------------------------------------------------------
;clc
; Switch to the BIOS (= request low memory size)
;int 0x12
;jmp 0x9d0000
;----------------------------------------------;
; Bootloader signature must be located
; at bytes #511 and #512.
; Fill with 0 in between.
; $ = address of the current line
; $$ = address of the 1st instruction
;----------------------------------------------;
times 510 - ($-$$) db 0
dw 0xaa55
Code: Select all
#define WHITE_TXT 0x07 /* light gray on black text */
void k_clear_screen();
unsigned int k_printf(char *message, unsigned int line);
void main(void);
void main(void) {
unsigned char* vga = (unsigned char*) 0xb8000;
vga[0] = 'H'; //need to make sure that this is a character
vga[1] = 0x09; //append the attribute byte
k_main();
for(;;); //make sure our kernel never stops, with an infinite loop
}
/* simple kernel written in C */
void k_main()
{
k_clear_screen();
k_printf("Jumped to the kernel!", 0);
};
/* k_clear_screen : to clear the entire text screen */
void k_clear_screen()
{
char *vidmem = (char *) 0xb8000;
unsigned int i=0;
while(i < (80*25*2))
{
vidmem[i]=' ';
i++;
vidmem[i]=WHITE_TXT;
i++;
};
};
/* k_printf : the message and the line # */
unsigned int k_printf(char *message, unsigned int line)
{
char *vidmem = (char *) 0xb8000;
unsigned int i=0;
i=(line*80*2);
while(*message!=0)
{
if(*message=='\n') // check for a new line
{
line++;
i=(line*80*2);
*message++;
} else {
vidmem[i]=*message;
*message++;
i++;
vidmem[i]=WHITE_TXT;
i++;
};
};
return(1);
}
Code: Select all
#include <stdio.h>
#include <sys/sysinfo.h>
#include <unistd.h>
#include <stdlib.h>
void main() {
/*const short color = 0x0F00;
const char* hello = "Hello from c file!";
short* vga = (short*)0xb8000;
for (int i = 0; i<16;++i)
vga[i+80] = color | hello[i];*/
//clrscr();
printf("Hello!");
for(;;) {}
}