October 26, 2015 I need D to do (asm+D)bootloader. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrea Fontana | 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 # 定义并实现了bootloader最先执行的函数start,此函数进行了一定的初始化,完成了 # 从实模式到保护模式的转换,并调用bootmain.c中的bootmain函数 #include <asm.h> # Start the CPU: switch to 32-bit protected mode, jump into C. # The BIOS loads this code from the first sector of the hard disk into # memory at physical address 0x7c00 and starts executing in real mode # with %cs=0 %ip=7c00. # gdt 全局描述符表内的数组索引 .set PROT_MODE_CSEG, 0x8 # kernel code segment selector .set PROT_MODE_DSEG, 0x10 # kernel data segment selector .set CR0_PE_ON, 0x1 # protected mode enable flag .globl start start: .code16 # Assemble for 16-bit mode cli # 禁用中断 cld # 字符串操作设定为递增 si++ di++ ,cld的作用是将direct flag标志位清零 # Set up the important data segment registers (DS, ES, SS). xorw %ax, %ax # Segment number zero movw %ax, %ds # -> Data Segment movw %ax, %es # -> Extra Segment movw %ax, %ss # -> Stack Segment # A20地址线控制打开工作 # Enable A20: # 为了向后兼容早期的PC机,让物理地址线20接低电平 # 如果A20是关闭的,16bit的寻址范围2^20是1M,如果是打开的,那么就是2^21次方, # 但是寻址还是FFFFh:FFFFh=FFFF0h+FFFFh=10FFEFh=1M+64K-16Bytes seta20.1: inb $0x64, %al # Wait for not busy testb $0x2, %al jnz seta20.1 #测试 bit 1 是不是为0,如果不是跳回去继续执行 # 对于键盘的8042控制芯片 0x64是命令端口 0xd1 代表写命令 movb $0xd1, %al # 0xd1 -> port 0x64 outb %al, $0x64 seta20.2: inb $0x64, %al # Wait for not busy testb $0x2, %al jnz seta20.2 # 设置写命令后 给0x60端口 发送命令数据0xdf就是打开A20地址线,0xdd就是关闭 movb $0xdf, %al # 0xdf -> port 0x60 outb %al, $0x60 # 转入保护模式,这里需要指定一个临时的GDT,来翻译逻辑地址。 # 这里使用的GDT通过gdtdesc段定义,它翻译得到的物理地址和虚拟地址相同, # 所以转换过程中内存映射不会改变 lgdt gdtdesc # 启动保护模式前建立好的段描述符合段描述符表 # 打开保护模式标志位,相当于按下了保护模式的开关。 # cr0寄存器的第0位就是这个开关,通过CR0_PE_ON或cr0寄存器,将第0位置1 movl %cr0, %eax orl $CR0_PE_ON, %eax movl %eax, %cr0 # 由于上面的代码已经打开了保护模式了,所以这里要使用逻辑地址, # 而不是之前实模式的地址了。这里用到了PROT_MODE_CSEG, # 他的值是0x8。根据段选择子的格式定义,0x8就翻译成: # INDEX TI CPL # 0000 0000 0000 1 00 0 # INDEX代表GDT中的索引,TI代表使用GDTR中的GDT, CPL代表处于特权级。 # PROT_MODE_CSEG选择子选择了GDT中的第1个段描述符。 # 这里使用的gdt就是变量gdt,下面可以看到gdt的第1个段描述符的基地址是0x0000, # 所以经过映射后和转换前的内存映射的物理地址一样。0000:7C00=0x00007C00 0000:protcseg 都是相对于物理内存0000基址的 ljmp $PROT_MODE_CSEG, $protcseg .code32 # Assemble for 32-bit mode protcseg: # 重新初始化各个段寄存器。也就是采用平坦式内存方式, # 代码段同其它段都采用一个内存空间 movw $PROT_MODE_DSEG, %ax # 自定义数据段选择子,因为段选择子是16位的 movw %ax, %ds # -> DS: Data Segment movw %ax, %es # -> ES: Extra Segment movw %ax, %fs # -> FS movw %ax, %gs # -> GS movw %ax, %ss # -> SS: Stack Segment # 栈顶设定在start处,也就是地址0x7c00处, # 低地址 0x0000 ^ 此地址为栈基址 0000 # call函数将返回地址入栈,将控制权交给bootmain # /|\ movl $0x0, %ebp # | movl $start, %esp # | call bootmain # 地址 0x7C00 | 栈顶指针 # bootmain 如果返回,就会在此处死循环,但是目前的bootmain的函数不会返回了,因为他内部就会死循环 spin: jmp spin # 注意以下数据结构 # Bootstrap GDT .p2align 2 # 调整为4字节对齐 # 3个段描述符,每个段描述符占8字节,共24字节 # gdtdesc指出了全局描述符表(可以看成是段描述符组成的一个数组)的起始位置在gdt符号处, # 而gdt符号处放置了三个段描述符的信息 # 第一个是NULL段描述符,没有意义,表示全局描述符表的开始 # 紧接着是代码段描述符(位于全局描述符表的0x8处的位置),具有可读(STA_R)和可执行(STA_X)的属性, # 并且段起始地址为0,段大小为4GB; # 接下来是数据段描述符(位于全局描述符表的0x10处的位置),具有可读(STA_R)和可写(STA_W)的属性, # 并且段起始地址为0,段大小为4GB。 gdt: SEG_NULLASM # null seg NULL段 SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff) # code seg for bootloader and kernel CODE段 SEG_ASM(STA_W, 0x0, 0xffffffff) # data seg for bootloader and kernel DATA段 gdtdesc: .word 0x17 # sizeof(gdt) - 1 类似于数组 数组是0开始的,所以数组长度就要减1 .long gdt # address gdt ***************************************************************************** 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 |
October 26, 2015 I want D to build OS,only with D | ||||
---|---|---|---|---|
| ||||
Posted in reply to guodemone | kill C,kill C++,only D I like D,so to build OS(Dlang).but dmd,gdc,ldc. There is no example of a method to write OS(bootloader,)Including compiled, linked fashion |
October 26, 2015 Re: I want D to build OS,only with D | ||||
---|---|---|---|---|
| ||||
Posted in reply to guodemone | On Monday, 26 October 2015 at 15:54:52 UTC, guodemone wrote: > There is no example of a method to write OS(bootloader,)Including compiled, linked fashion Chapter 11 of my book https://www.packtpub.com/application-development/d-cookbook shows how you can get started. Though the runtime requirements have probably changed since then, so it may not work exactly as presented. Starting example code here: http://arsdnet.net/dcode/book/chapter_11/01/ |
October 26, 2015 chinese have 1.5 billion people,change coding people 0.02% study, So the language is super language | ||||
---|---|---|---|---|
| ||||
Posted in reply to guodemone | I like D. |
October 26, 2015 Training your language fans | ||||
---|---|---|---|---|
| ||||
Posted in reply to guodemone | Let hobby into a need, let your D language into university tutorial(of china). Coffee is grown out(no), but drink out(yes). Relative to his popularity |
October 26, 2015 Re: I need D to do (asm+D)bootloader. | ||||
---|---|---|---|---|
| ||||
Posted in reply to guodemone Attachments:
| On 26 Oct 2015 4:50 pm, "guodemone via Digitalmars-d-announce" < digitalmars-d-announce@puremagic.com> wrote: > > sorry,My english is poot. > > file asm.h > This is for D.learn, I'd suggest asking there (probably putting your code on a pastebin site to link in). |
October 26, 2015 Re: I want D to build OS,only with D | ||||
---|---|---|---|---|
| ||||
Posted in reply to guodemone | On Monday, 26 October 2015 at 15:54:52 UTC, guodemone wrote: > kill C,kill C++,only D > > I like D,so to build OS(Dlang).but dmd,gdc,ldc. > > There is no example of a method to write OS(bootloader,)Including compiled, linked fashion 欢迎你!谢谢你的问题。请你抄写这个问题在这儿:http://forum.dlang.org/group/learn 对不起我说中文说得不好 |
October 26, 2015 Re: I need D to do (asm+D)bootloader. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Iain Buclaw | On 10/26/2015 10:19 AM, Iain Buclaw via Digitalmars-d-announce wrote:
> This is for D.learn, I'd suggest asking there (probably putting your code on a
> pastebin site to link in).
Does pastebin code last forever? If it is ephemeral, it'd be better to include it in the posting.
|
October 27, 2015 你的中文说的很好了,谢谢你的解答 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Meta | 非常感谢,希望DLang可以进入中国的大学,那样Dlang会更有前途,我在为这个目标努力着。 |
October 27, 2015 I will continue to complete the OS with Dlang | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | I will continue to complete the OS with Dlang. I will tell a lot of Chinese programmers how to write easy to use Dlang OS is fast. I sincerely wish Dlang. 我会继续用D来完成这个OS。 我要告诉所有的中国程序员,用D去完成一个OS是多么的快捷、方便。 我衷心的祝福D语言。 |
Copyright © 1999-2021 by the D Language Foundation