digitalmars.D.learn - asm+D build bootloader
- guodemone (244/244) Oct 27 2015 sorry,My english is poot.
- Kagamin (2/2) Oct 27 2015 You chose quite advanced topic. Maybe you want to build common
- guodemone (3/3) Oct 27 2015 Asm + D with the ability to write on behalf of Clang bootloader,
- lobo (56/59) Oct 27 2015 Can ldc work with C header files? I don't think it can but I
sorry,My english is poot. file asm.h /* 是bootasm.S汇编文件所需要的头文件,主要是一些与X86保护模式的段访问方式相关的宏定义 */ #ifndef __BOOT_ASM_H__ #define __BOOT_ASM_H__ /* Assembler macros to create x86 segments */ /* Normal segment */ #define SEG_NULLASM \ .word 0, 0; \ .byte 0, 0, 0, 0 #define SEG_ASM(type,base,lim) \ .word (((lim) >> 12) & 0xffff), ((base) & 0xffff); \ .byte (((base) >> 16) & 0xff), (0x90 | (type)), \ (0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff) /* Application segment type bits */ #define STA_X 0x8 // 可执行 #define STA_E 0x4 // 向下扩展段(非可执行段) #define STA_C 0x4 // 一致性代码段(只执行) #define STA_W 0x2 // 段可写(非可执行段) #define STA_R 0x2 // 段可读 (可执行段) #define STA_A 0x1 // 可访问 #endif /* !__BOOT_ASM_H__ */ ********************************************************** file bootasm.S #include <asm.h> into mode .globl start start: ,cld的作用是将direct flag标志位清零 seta20.1: testb $0x2, %al 是不是为0,如果不是跳回去继续执行 outb %al, $0x64 seta20.2: testb $0x2, %al jnz seta20.2 发送命令数据0xdf就是打开A20地址线,0xdd就是关闭 outb %al, $0x60 启动保护模式前建立好的段描述符合段描述符表 movl %cr0, %eax orl $CR0_PE_ON, %eax movl %eax, %cr0 CPL代表处于特权级。 000:7C00=0x00007C00 0000:protcseg 都是相对于物理内存0000基址的 ljmp $PROT_MODE_CSEG, $protcseg protcseg: 自定义数据段选择子,因为段选择子是16位的 0x0000 ^ 此地址为栈基址 0000 /|\ | | | 栈顶指针 spin: jmp spin gdt: bootloader and kernel CODE段 and kernel DATA段 gdtdesc: 数组是0开始的,所以数组长度就要减1 ***************************************************************************** file bootmain.c /* 定义并实现了bootmain函数实现了通过屏幕、串口和并口显示字符串 */ //#include <types.h> //#include <x86.h> #define COM1 0x3F8 #define CRTPORT 0x3D4 #define LPTPORT 0x378 #define COM_TX 0 // Out: Transmit buffer (DLAB=0) #define COM_LSR 5 // In: Line Status Register #define COM_LSR_TXRDY 20 // Transmit buffer avail static uint16_t *crt = (uint16_t *) 0xB8000; // CGA memory /* stupid I/O delay routine necessitated by historical PC design flaws */ static void delay(void) { inb(0x84); inb(0x84); inb(0x84); inb(0x84); } /* 考虑到简单性,在proj1中没有对并口设备进行初始化,通过并口进行输出的过程也很简单: 第一步:执行inb指令读取并口的I/O地址(LPTPORT + 1)的值,如果发现发现读出的值代表并口忙, 则空转一小会再读; 如果发现发现读出的值代表并口空闲,则执行outb指令把字符写到并口 I/O地址(LPTPORT ), 这样就完成了一个字符的并口输出。 */ /* lpt_putc - copy console output to parallel port */ static void lpt_putc(int c) { int i; for (i = 0; !(inb(LPTPORT + 1) & 0x80) && i < 12800; i ++) { delay(); } outb(LPTPORT + 0, c); outb(LPTPORT + 2, 0x08 | 0x04 | 0x01); outb(LPTPORT + 2, 0x08); } /* 通过CGA显示控制器进行输出的过程也很简单:首先通过in/out指令获取当前光标位置; 然后根据得到的位置计算出显存的地址,直接通过访存指令写内存来完成字符的输出; 最后通过in/out指令更新当前光标位置。 */ /* cga_putc - print character to console */ static void cga_putc(int c) { int pos; // cursor position: col + 80*row. outb(CRTPORT, 14); pos = inb(CRTPORT + 1) << 8; outb(CRTPORT, 15); pos |= inb(CRTPORT + 1); if (c == '\n') { pos += 80 - pos % 80; } else { crt[pos ++] = (c & 0xff) | 0x0700; } outb(CRTPORT, 14); outb(CRTPORT + 1, pos >> 8); outb(CRTPORT, 15); outb(CRTPORT + 1, pos); } /* 通过串口进行输出的过程也很简单:第一步:执行inb指令读取串 的I/O地址(COM1 + COM_LSR)的值, 如果发现发现读出的值代表串口忙,则空转一小会(0x84是什么地址???); 如果发现发现读出的值代表串口空闲,则执行outb指令把字符写到串 的I/O地址(COM1 + COM_TX), 这样就完成了一个字符的串口输出。 */ /* serial_putc - copy console output to serial port */ static void serial_putc(int c) { int i; for (i = 0; !(inb(COM1 + COM_LSR) & COM_LSR_TXRDY) && i < 12800; i ++) { delay(); } outb(COM1 + COM_TX, c); } /* 显示字符的函数接口*/ /* 一个cons_putc函数接口,完成字符的输出*/ /* cons_putc - print a single character to console*/ static void cons_putc(int c) { lpt_putc(c); cga_putc(c); serial_putc(c); } /* 提供了一个cons_puts函数接口:完成字符串的输出*/ /* cons_puts - print a string to console */ static void cons_puts(const char *str) { int i; for (i = 0; *str != '\0'; i ++) { cons_putc(*str ++); } } /* bootmain - the entry of bootloader */ void bootmain(void) { cons_puts("This is a bootloader: Hello world!!"); /* do nothing */ while (1); } *************************************************** These codes(asm.h bootasm.S bootmain.c) trans to (asm.h bootasm.S bootmain.d). ldc -c asm.h bootasm.S bootmain.d ld bootasm.o bootmain.o of outbin.o How to build?
Oct 27 2015
You chose quite advanced topic. Maybe you want to build common skills in system programming first?
Oct 27 2015
Asm + D with the ability to write on behalf of Clang bootloader, and prove that he can completely replace Clang. This is my wish.
Oct 27 2015
On Tuesday, 27 October 2015 at 12:13:13 UTC, guodemone wrote:sorry,My english is poot. file asm.h [...]Can ldc work with C header files? I don't think it can but I could be wrong. Here's how I build my 32-bit bootloader and link with my kernel main (you will have to replace names etc.): --- nasm -felf -o kickstart32.o kickstart32.s (I don't have an asm.h) gdc -m32 -gdwarf-2 -nostdlib -fPIC -c -o kernel32.main.o kmain.d ld -nodefaultlibs -melf_i386 -z max-page-size=0x1000 -T linker32.ld -o kernel32.bin kickstart32.o kernel32.main.o --- For this build setup you will need a linker script. Here's mine in case you don't have one. 'kickstart' is the entry point in my kickstart.s. Replace names and offsets as required for your code. --- /* Use -melf_i386 or -melf64_x86-64 * to specify the architecture * ld -nodefaultlibs -melf_i386 -z max-page-size=0x1000 -T <linker_script> -o <output_binary> */ ENTRY (kickstart) SECTIONS{ . = 0x00100000; .text :{ code = .; _code = .; __code = .; *(.text) *(.rodata) } .rodata ALIGN (0x1000) : { *(.rodata) } .data ALIGN (0x1000) : { data = .; _data = .; __data = .; *(.data) start_ctors = .; *(.ctors) end_ctors = .; start_dtors = .; *(.dtors) end_dtors = .; } .bss : { sbss = .; bss = .; _bss = .; __bss = .; *(COMMON) *(.bss) ebss = .; } end = .; _end = .; __end = .; } --- I got a lot of info from these sites: https://www.cs.cmu.edu/~410-s07/p4/p4-boot.pdf https://en.wikibooks.org/wiki/X86_Assembly/Bootloaders http://wiki.osdev.org/Bare_bones (NOTE: wiki.osdev.org has a lot of incorrect information, but it was useful as a starting point when I got stuck moving to a 64-bit kernel) bye, lobo
Oct 27 2015
My english is poor. My code to build is wrong.so need make some improvements. I would like to refer to your 32-bit code, make some improvements.
Oct 27 2015
My english is poor. My code to build is wrong.so need make some improvements. I would like to refer to your 32-bit code, make some improvements. My Email: 704975494 qq.com very very thank you.
Oct 28 2015
On Wednesday, 28 October 2015 at 11:01:14 UTC, guodemone wrote:My english is poor. My code to build is wrong.so need make some improvements. I would like to refer to your 32-bit code, make some improvements. My Email: 704975494 qq.com very very thank you.I've uploaded a dummy kernel with bootloader to Github. Hopefully it will help you. https://github.com/swamplobo/lyrebirdos A few points: * The Makefile uses DMD but if you prefer you can use the gdc_Makefile to switch compilers easily. * This example uses GRUB, which you can replace this if you wish. I did once I got things working (I've now gone back to GRUB because it has some nice features). * I use qemu, VirtualBox and real hardware to test. I recommend testing in a VM before trying real hardware. * The name Lyrebird OS is just the name I chose, rename to whatever you like. * Keep at it because it's very rewarding watching your own kernel grow. bye, lobo
Oct 28 2015
衷心的谢谢你,(very very........very thank you in english)
Oct 28 2015
On Thursday, 29 October 2015 at 06:13:17 UTC, guodemone wrote:衷心的谢谢你,(very very........very thank you in english)You're welcome, hope it helps :)
Oct 29 2015
On Thursday, 29 October 2015 at 06:13:17 UTC, guodemone wrote:衷心的谢谢你,(very very........very thank you in english)请问,你是学生吧?你是哪个中国大学的学生?我也希望DLang可以进入中国的大学,祝你的OS好运!
Oct 29 2015
我是一个程序员,就是因为英语不好,技术进步很慢,从遇到D语言开始,我开始大量的接触底层开发,D给了我很多原先没有接触到的知识。所以让D成为国内大学的主流语言是非常合适的。他的编译器容易获得,易于安装,而且夸平台,比C更容易入门,又比C++易学,同时拥有动态语言的特性。如果能够进入大学教程的话,会是国内软件的一个飞速发展的工具软件了。
Oct 29 2015