我正在制作一个自定义操作系统.我有两个nasm文件:
boot.asm:
[BITS 16] ;tell the assembler that its a 16 bit code
[ORG 0x7C00] ;Origin, tell the assembler that where the code will
;be in memory after it is been loaded
INT 0x13
JMP $ ;infinite loop
TIMES 510 - ($ - $$) db 0 ;fill the rest of sector with 0
DW 0xAA55 ; add boot signature
Run Code Online (Sandbox Code Playgroud)
start.asm:
[BITS 16]
MOV AL, 72
CALL PrintCharacter
MOV AL, 101
CALL PrintCharacter
MOV AL, 108
CALL PrintCharacter
MOV AL, 108 …Run Code Online (Sandbox Code Playgroud) 我用c中的内核创建了一个桌面操作系统,打印出"hello world".我正在尝试为我的操作系统制作一个GUI(自定义窗口管理器,按钮),但我遇到了麻烦.我看了一个教程:
http://www.osdever.net/tutorials/view/gui-development
是否有适用于C桌面操作系统的GUI教程?
ps没有Linux,没有DOS.只有C标准.
我正在尝试使用C创建一个简单的内核.一切都加载并正常工作,我可以访问视频内存并显示字符,但是当我尝试实现一个简单的put函数由于某种原因它不起作用.我已经尝试了自己的代码和其他代码.此外,当我尝试使用在函数外声明的变量时,它似乎不起作用.这是我自己的代码:
#define PUTCH(C, X) pos = putc(C, X, pos)
#define PUTSTR(C, X) pos = puts(C, X, pos)
int putc(char c, char color, int spos) {
volatile char *vidmem = (volatile char*)(0xB8000);
if (c == '\n') {
spos += (160-(spos % 160));
} else {
vidmem[spos] = c;
vidmem[spos+1] = color;
spos += 2;
}
return spos;
}
int puts(char* str, char color, int spos) {
while (*str != '\0') {
spos = putc(*str, color, spos);
str++;
}
return spos;
} …Run Code Online (Sandbox Code Playgroud) Bootloader分为两个阶段.第一阶段用汇编语言编写,只加载第二阶段,第二阶段在C阶段.阶段1加载C中的代码到地址0x0500:0,并跳转到那里.Stage2必须写"hello message"并停止.
我尝试了不同的方法将起始地址设置为原始二进制文件:(但没有任何效果)
cc -nostartfiles -nostdlib -c stage2.c
ld -s -T scrptfile.ld stage2.o /* I'm using ld just to set starting address of executable */
objcopy -O binary stage2 stage2.bin /* delete all unuseful data */
Run Code Online (Sandbox Code Playgroud)
链接器脚本
SECTIONS
{
. = 0x0500;
.text : { *(.text)}
.data : { *(.data)}
.bss : { *(.bss)}
}
Run Code Online (Sandbox Code Playgroud)
也许我删除objcopy somethnig应删除.
那我怎么能执行这个stage2.bin呢?
据我所知,使用32位长度指令编写C代码,当原始二进制只允许16?
PS参数-set-start(objcopy)返回错误:无效的bfd目标.这是因为输出文件是二进制的?
谢谢你的回答.
我指的是Broken Thorn的OS开发教程。我目前处于执行第二阶段引导加载程序以加载GDT并进入保护模式的阶段。
我了解了GDT的工作原理以及如何进入保护模式。但是,我对加载cr0寄存器后执行的第一条指令感到困惑:
jmp 08h:Stage3 ; far jump to fix CS. Remember that the code selector is 0x8!
Run Code Online (Sandbox Code Playgroud)
此时,CS尚未加载指向代码描述符的选择器值,并且我们已经处于保护模式。此CS值可能与用于执行实模式指令的值不同,因此,增加IP的值也将导致地址不同于的地址jmp。那么这是否会导致基于CS的值执行一些垃圾代码?还是我缺少什么?
我正在用C开发一个小玩具内核.我需要从键盘获取用户输入.到目前为止,我已inb使用以下代码实现:
static inline uint8_t inb(uint16_t port) {
uint8_t ret;
asm volatile("inb %1, %0" : "=a"(ret) : "Nd"(port));
return ret;
}
Run Code Online (Sandbox Code Playgroud)
我知道"=a"约束意味着al/ax/eax将被复制ret为输出,但我仍然对"Nd"约束感到困惑.谁能提供一些有关为什么需要这种约束的见解?或者为什么我不能只使用通用寄存器约束"r"或"b"?任何帮助,将不胜感激.
我正在编写一个包含我的32位内核的Multiboot兼容的ELF可执行文件.我的主要问题是我在生成可执行文件时收到一系列链接器错误:
重定位被截断以适合:R_386_16对``.text'
链接器脚本,代码和构建脚本如下
我决定尝试在我的操作系统中实现VESA VBE图形.我在OSDev论坛中发现了一个现有的VESA驱动程序,我试图将它集成到我自己的操作系统中.我尝试将它添加到我的源目录,用NASM组装并将其链接到LD的最终可执行文件中.我收到的具体错误是:
vesa.asm:(.text+0x64): relocation truncated to fit: R_386_16 against `.text'
obj/vesa.o: In function `svga_mode':
vesa.asm:(.text+0x9d): relocation truncated to fit: R_386_16 against `.text'
vesa.asm:(.text+0xb5): relocation truncated to fit: R_386_16 against `.text'
obj/vesa.o: In function `done':
vesa.asm:(.text+0xc7): relocation truncated to fit: R_386_16 against `.text'
Run Code Online (Sandbox Code Playgroud)
导致错误的行(按顺序)如下:
mov ax,[vid_mode]
mov cx,[vid_mode]
mov bx,[vid_mode]
jmp 0x8:pm1
Run Code Online (Sandbox Code Playgroud)
我还评论了"链接器错误"的行
这是文件(vesa.asm):
BITS 32
global do_vbe
save_idt: dd 0
dw 0
save_esp: dd 0
vid_mode: dw 0
do_vbe: …Run Code Online (Sandbox Code Playgroud) 关于标题类似的stackoverflow有很多问题。我读了所有这些文章,但没有一个回答我的问题。这就是为什么我打开这个问题。
我正在用汇编器和C创建一个操作系统。我发现必须将C代码编译为二进制格式,提取文本部分并将其保存为文件,然后将其转换为ISO,然后将其安装到diskete的虚拟光驱中,然后在VirtualBox中加载我的操作系统。因此,这是我要避免的许多工作。我不想每次都将二进制文件转换为ISO。
因此,我决定将操作系统的二进制计算机代码放入虚拟硬盘驱动器(VDI文件),然后将其设置为引导顺序的顶部并加载,而不是从虚拟光盘驱动器加载ISO。
我正在研究VDI工作原理,发现它通常是按名称分配的,并且只存储数据的开头。因此,的开头VDI代表标题,其余的代表存储在虚拟驱动器上的实际数据。因此,我发现数据从某个地址开始(就我而言,它是0x00200000从VDI文件的开头开始)。
然后,我基本上VDI使用pattern 从该地址填充到文件末尾55 AA。因此,我想它现在意味着磁盘是可引导的(因为第一个扇区的末尾仍是签名55 AA)。
我启动了虚拟机,它说:
找不到可启动媒体!系统停止
有什么办法解决这个问题?为什么我的虚拟磁盘仍然无法启动?
这是实际的VDI文件:1.vdi
好吧,我已经在程序集中编写了一个引导加载程序,并尝试从中加载C内核。
这是引导程序:
bits 16
xor ax,ax
jmp 0x0000:boot
extern kernel_main
global boot
boot:
mov ah, 0x02 ; load second stage to memory
mov al, 1 ; numbers of sectors to read into memory
mov dl, 0x80 ; sector read from fixed/usb disk ;0 for floppy; 0x80 for hd
mov ch, 0 ; cylinder number
mov dh, 0 ; head number
mov cl, 2 ; sector number
mov bx, 0x8000 ; load into es:bx segment :offset of buffer
int 0x13 ; …Run Code Online (Sandbox Code Playgroud) 还是我,我的idt.S文件(使用gcc编译的Intel语法)出现了新问题。当我尝试编译以下代码时:
load_idt:
mov edx, (esp + 4) ; On this line
lidt (edx)
sti
ret
Run Code Online (Sandbox Code Playgroud)
我收到一个我真的不知道如何解决的错误:
Error: too many memory references for `mov'
Run Code Online (Sandbox Code Playgroud) osdev ×10
x86 ×8
assembly ×4
bootloader ×4
gcc ×4
kernel ×4
nasm ×2
c ×1
elf ×1
intel-syntax ×1
ld ×1
linker ×1
pointers ×1
virtualbox ×1