www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - asm+D build bootloader

reply guodemone <704975494 qq.com> writes:
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
next sibling parent reply Kagamin <spam here.lot> writes:
You chose quite advanced topic. Maybe you want to build common 
skills in system programming first?
Oct 27 2015
parent guodemone <704975494 qq.com> writes:
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
prev sibling parent reply lobo <swamplobo gmail.com> writes:
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
next sibling parent reply guodemone <704975494 qq.com> writes:
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
parent guodemone <704975494 qq.com> writes:
thank you.
Oct 27 2015
prev sibling next sibling parent guodemone <704975494 qq.com> writes:
704975494 qq.com
very very thank you.
Oct 28 2015
prev sibling parent reply guodemone <704975494 qq.com> writes:
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
parent reply lobo <swamplobo gmail.com> writes:
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
parent reply guodemone <704975494 qq.com> writes:
衷心的谢谢你,(very very........very thank you in english)
Oct 28 2015
next sibling parent lobo <swamplobo gmail.com> writes:
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
prev sibling parent reply Meta <jared771 gmail.com> writes:
On Thursday, 29 October 2015 at 06:13:17 UTC, guodemone wrote:
 衷心的谢谢你,(very very........very thank you in english)
请问,你是学生吧?你是哪个中国大学的学生?我也希望DLang可以进入中国的大学,祝你的OS好运!
Oct 29 2015
parent guodemone <704975494 qq.com> writes:
我是一个程序员,就是因为英语不好,技术进步很慢,从遇到D语言开始,我开始大量的接触底层开发,D给了我很多原先没有接触到的知识。所以让D成为国内大学的主流语言是非常合适的。他的编译器容易获得,易于安装,而且夸平台,比C更容易入门,又比C++易学,同时拥有动态语言的特性。如果能够进入大学教程的话,会是国内软件的一个飞速发展的工具软件了。
Oct 29 2015