Author Topic: Assembly and C, how to do it correctly ?  (Read 18654 times)

Offline gomi

  • Jr. Member
  • *
  • Posts: 9
Assembly and C, how to do it correctly ?
« on: November 21, 2020, 02:39:40 PM »
Hello, I am trying to make a very simple program.

I tried to understand based on this resource: https://blog.ghaiklor.com/2017/11/02/how-to-implement-a-second-stage-boot-loader/
I do not know much about assembly. Note that it may contain partly wrong code. Still, I tested it on qemu.

boot.asm:
Code: [Select]

[org 0x7c00] ; sets the start address
[bits 16] ; use 16 bits

;; memory offset where our kernel is located
KERNEL_OFFSET equ 0x1000

;; save the boot drive number
mov [BOOT_DRIVE], dl

;; update base and stack pointers
mov bp, 0x9000
mov sp, bp


init:
  mov si, msg ; loads the address of "msg" into SI register
  mov ah, 0x0e ; sets AH to 0xe (function teletype)
print_char:
  lodsb ; loads the current byte from SI into AL and increments the address in SI
  cmp al, 0 ; compares AL to zero
  je done ; if AL == 0, jump to "done"
  int 0x10 ; print to screen using function 0xe of interrupt 0x10
  jmp print_char ; repeat with next byte

;; call routine that loads kernel into memory
call load_kernel_into_memory

;; switch to Protected Mode
call switch_to_pm
jmp $

;; routine reads kernel from disk into memory
load_kernel_into_memory:
;; store all register values
pusha

;; set up parameters for disk_read routine
mov bx, KERNEL_OFFSET
mov dh, 15
mov dl, [BOOT_DRIVE]
call disk_read

;; restore register values and ret
popa
ret
;

[bits 32]

begin_pm:
;; Check if we can move from Protected Mode to Long Mode
;; If something went wrong (detect_lm shouldn't return at all)
;; we call execute_kernel in x32 Protected Mode
call detect_lm
call execute_kernel
jmp $

[bits 64]

begin_lm:
;; In case, if detect_lm and switch_to_lm works fine, call kernel in x64 mode
call execute_kernel
jmp $
;
execute_kernel:
call KERNEL_OFFSET
jmp $
;
;You can download all full project from the link I provided or you can get it from totorial source page link I added above.
%include "ARMNET/disk/disk_read.asm";
%include "ARMNET/lm/detect_lm.asm";
%include "ARMNET/lm/switch_to_lm.asm";
%include "ARMNET/pm/gdt.asm"
%include "ARMNET/pm/switch_to_pm.asm"
%include "ARMNET/print/print_string.asm";
%include "ARMNET/print/print_nl.asm";

BOOT_DRIVE: db 0

done:
  hlt ; stop execution
  msg: db "PROGRAM STARTED", 0x0a; we need to explicitely put the zero byte here
;

times 510-($-$$) db 0 ; fill the output file with zeroes until 510 bytes are full
dw 0xaa55 ; magic number that tells the BIOS this is bootable

loader.asm
Code: [Select]
global _start

[bits 32]
[extern _kernel_main]

_start:
  call [_kernel_main]
  jmp $

loader.c
Code: [Select]
extern void kernel_main() {
for (int i = 0; i < 26; i++) {
char c = 0x41 + i;

asm(
"mov %0, %%al;"
"mov $0x0E, %%ah;"
"int $0x10;"
:
: "r" (c)
);
}
}

For "C" link I did:

1)nasm loader.asm -f elf32 -o loader_entry.o
2)gcc -O0 -g -ffreestanding -m32 -c loader.c -o loader.o
3) ld -o "loader.tmp" -m i386pe -Ttext 0x1000 -T NUL loader_entry.o loader.o
4)type boot.bin loader.bin > image.bin

When I test it on qemu I do not see "C" file output.

What I did wrong ?


FILES I ADDED DOES NOT CONTAIN "C". Interestingly, C containing boot works. Prints the text from stage 1. However, not "C" text. Here is the problem. On totorial page, that prints the alphabet. One more point I put _kernel_main and in "C" thats kernel_main otherwise that does not compile.

ALL FILES:https://filebin.net/isdh9p2sm29dhgrs

IMAGE-QEMU-OUTPUT:https://ibb.co/YyVccGW

I also addet files as attachment.

Thank you.
« Last Edit: November 21, 2020, 09:39:59 PM by gomi »

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Assembly and C, how to do it correctly ?
« Reply #1 on: November 24, 2020, 01:09:46 AM »
Hi gomi,

I don't know much C. so probably can't help you much,
It looks like you may have switched the CPU into 32 bit mode and then tried to use BIOS int 10h. That won't work - BIOS interrupts are 16 bit.

You can probably find text screen memory at 0xB8000 (and subsequent). Putting ascii vharacter values there may work. Good luck!

Best,
Frank