Linking C, C++ and assembly

0

I'm writing little "kernel" that displays "Hello world!" on the screen. I have working putc (put char) function so I can do it (and I did it) with 12 putc function calls but I want do it with puts (put string) function and I want to write it in C++. I know that I can make it in C but I'll need C with C++ linking in the future... So why not do it right now?

Here is my kernel.c code:

extern void putc(char, char);
extern void puts(char*, char);
extern void clear(void);

void start_kernel(void)
{

  clear();
  puts("Hello world!", 7);
  putc('H', 7);
  putc('e', 7);
  putc('l', 7);
  putc('l', 7);
  putc('o', 7);
  putc(' ', 7);
  putc('w', 7);
  putc('o', 7);
  putc('r', 7);
  putc('l', 7);
  putc('d', 7);
  putc('!', 7);

  for(;;);

}

I changed the puts.cpp code so that it should display the first letter of the string on the screen... but it doesn't...

puts.cpp:

extern "C" void putc(char, char);

extern "C"
{

  void puts(char *s, char color)
  {

    putc(*s, 7);

  }

}

This function clears 80x25 VGA buffor it have 4000 bytes size

clear.asm:

BITS 32

GLOBAL clear

clear:

  push eax

  mov eax, 0xb8000
  dec eax

  L1:

    inc eax
    mov byte [eax], 0
    cmp eax, 0xb8fa0
    jb L1

  pop eax

  ret

putc.asm:

BITS 32

GLOBAL putc

putc:

  push eax

  mov eax, 0xb8000
  dec eax

  L1:

    inc eax
    cmp byte [eax], 0
    jnz L1

  mov [eax], edi
  mov [eax+1], esi

  pop eax

  ret

kernel.ld:

OUTPUT_FORMAT("binary")
ENTRY("_start")
SECTIONS {
.text 0x100000 : {
code = . ; _code = . ;
*(.text)
}
.data : {
*(.data)
}
.bss : {
bss = . ; _bss = . ;
*(.bss)
*(.COMMON)
}
end = . ; _end = . ;
}

start.asm:

BITS 64

section .text

  EXTERN code,bss,end

  mboot:

    dd 0x1BADB002
    dd 0x10001
    dd -(0x1BADB002+0x10001)
    dd mboot
    dd code
    dd bss
    dd end
    dd _start

  GLOBAL _start

  _start:

    cli
    mov esp,kstack+4096
    mov ax,0x10
    mov ds,ax
    mov es,ax
    mov fs,ax
    mov gs,ax
    lgdt [gdt_descr]
    jmp .1
    .1:
    push dword 0
    push dword 0
    push dword 0
    push dword L6

    EXTERN start_kernel
    push dword start_kernel
    ret

    L6:

      jmp L6

section .bss

  kstack: resd 1024

section .data

  gdt_descr:

    dw 256*8-1
    dd _gdt

  GLOBAL _gdt

  _gdt:

    dd 0,0
    dd 0x0000FFFF,0x00CF9A00
    dd 0x0000FFFF,0x00CF9200
    dd 0,0
    times 254 dd 0,0

link.bash script:

nasm start.asm -f elf64 -o start.o
nasm putc.asm -f elf64 -o putc.o
nasm clear.asm -f elf64 -o clear.o
gcc puts.cpp -std=c++0x -c -o puts.o
gcc kernel.c -O3 -fomit-frame-pointer -masm=intel -c -o kernel.o
ld -Tkernel.ld -o kernel.bin start.o kernel.o putc.o puts.o clear.o

After generating iso running it with qemu-system-x86_64 -hdd kernel.iso , it displays weird character (each time this same) and Hello world! Of course after placing this function in kernel.c file it displays HHello world!

Interesting thing is that after replacing gcc with clang++ (for puts.cpp) it displays another weird character (also each time this same)

After replacing puts() function content with putc('a', 7); it displays this letter correctly so it looks like there is a problem with passing arguments between C and C+++ not C++ and assembly but maybe I'm wrong...

c
assembly
vga
asked on Stack Overflow Jul 9, 2019 by Roman Kwaśniewski • edited Jul 9, 2019 by Roman Kwaśniewski

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0