链接C,C ++和汇编

时间:2019-07-09 18:13:26

标签: c assembly vga

我正在写显示“ Hello world!”的小“内核”。屏幕上。我有工作的putc(put char)函数,所以我可以用12个putc函数调用来做到(我做到了),但是我想用puts(put string)函数来实现,我想用C ++编写。我知道我可以用C语言实现它,但是将来我将需要使用C ++链接进行C语言...那为什么现在不这样做呢?

这是我的kernel.c代码:

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(;;);

}

我更改了puts.cpp代码,以便它应该在屏幕上显示字符串的第一个字母...但是没有...

puts.cpp:

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

extern "C"
{

  void puts(char *s, char color)
  {

    putc(*s, 7);

  }

}

此功能清除80x25 VGA buffor,它具有4000字节大小

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脚本:

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

用qemu-system-x86_64 -hdd kernel.iso生成iso运行它之后,它显示奇怪的字符(每次相同)和Hello world! 当然,将此功能放入kernel.c文件后,它会显示HHello世界!

有趣的是,用clang ++(对于puts.cpp)替换gcc后,它会显示另一个奇怪的字符(每次都相同)

用putc('a',7)替换puts()函数内容后;它正确显示了这封信,所以看起来好像在C和C ++之间传递参数而不是C ++和汇编程序时出现问题,但是也许我错了...

0 个答案:

没有答案