OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 11:32 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 33 posts ]  Go to page 1, 2, 3  Next
Author Message
 Post subject: Error compile GDT and Interrupt
PostPosted: Mon Jul 01, 2019 11:04 am 
Offline

Joined: Mon Jul 01, 2019 10:46 am
Posts: 24
Good evening all. Now, I am learning OS Development from James Molloy. But I've got problem here.
Error like this
Code:
ld -mi386pe -nostdlib --nmagic -T linker.ld -o kernel.pe loader.o kernel.o common.o monitor.o descriptor_table.o gdt.o isr.o interrupt.o
descriptor_table.o: In function `init_gdt':
/cygdrive/d/AnantaOS/src/descriptor_table.c:75: undefined reference to `gdt_flush'
interrupt.o:fake:(.text+0x150): undefined reference to `isr_handler'
interrupt.o:fake:(.text+0x6): undefined reference to `isr_common'
interrupt.o:fake:(.text+0x10): undefined reference to `isr_common'
interrupt.o:fake:(.text+0x1a): undefined reference to `isr_common'
interrupt.o:fake:(.text+0x24): undefined reference to `isr_common'
interrupt.o:fake:(.text+0x2e): undefined reference to `isr_common'
interrupt.o:fake:(.text+0x38): more undefined references to `isr_common' follow
make: *** [Makefile:14: kernel.pe] Error 1


I'm sorry, I don't using cross compiler (You know this is really bad habbit for OSDev). I'm using cygwin in Windows 10 for OSDevelopment. But I need help alot. I want continue this lesson more depth (I still newbie).

code in gdt.s
Code:
.section .text
.align 4

.global gdt_flush

gdt_flush:
    mov 4(%esp),%eax
    lgdt (%eax)
    mov $0x10,%ax
    mov %ax,%ds
    mov %ax,%es
    mov %ax,%fs
    mov %ax,%ss
    mov %ax,%gs
    jmp $0x08, $.flush

.flush:
    ret

.global idt_flush

idt_flush:
   mov 4(%esp),%eax
   lidt (%eax)
   ret


Interrupt code
Code:
.section .text
.align 4

.macro ISR_NOERR index
    .global _isr\index
    _isr\index:
        cli
        push $0
        push $\index
        jmp isr_common
.endm

.macro ISR_ERR index
    .global _isr\index
    _isr\index:
        cli
        push $\index
        jmp isr_common
.endm

/* Standard X86 interrupt service routines */
ISR_NOERR 0
ISR_NOERR 1
ISR_NOERR 2
ISR_NOERR 3
ISR_NOERR 4
ISR_NOERR 5
ISR_NOERR 6
ISR_NOERR 7
ISR_ERR   8
ISR_NOERR 9
ISR_ERR   10
ISR_ERR   11
ISR_ERR   12
ISR_ERR   13
ISR_ERR   14
ISR_NOERR 15
ISR_NOERR 16
ISR_NOERR 17
ISR_NOERR 18
ISR_NOERR 19
ISR_NOERR 20
ISR_NOERR 21
ISR_NOERR 22
ISR_NOERR 23
ISR_NOERR 24
ISR_NOERR 25
ISR_NOERR 26
ISR_NOERR 27
ISR_NOERR 28
ISR_NOERR 29
ISR_NOERR 30
ISR_NOERR 31
ISR_NOERR 127

.extern isr_handler

isr_common_stub:
    pusha
    mov %ds,%ax
    push %eax
    mov $0x10, %ax
    mov %ax, %ds
    mov %ax, %es
    mov %ax, %fs
    mov %ax, %gs

    call isr_handler

    pop %eax
    mov %ax, %ds
    mov %ax, %es
    mov %ax, %fs
    mov %ax, %gs

    popa
    add $8, %esp
    iret


Top
 Profile  
 
 Post subject: Re: Error compile GDT and Interrupt
PostPosted: Mon Jul 01, 2019 11:12 am 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 671
Windows 32-bit object file formats require externals to have a leading underscore. gdt_flush should be _gdt_flush in the assembly code. This is actually a side effect of not using a cross compiler and the types of things you have to concern yourself with when using a native toolchain for the host environment. If you did choose to use a cross compiler (which you have decided not to) you wouldn't have to concern yourself with this issue.


Top
 Profile  
 
 Post subject: Re: Error compile GDT and Interrupt
PostPosted: Mon Jul 01, 2019 9:31 pm 
Offline

Joined: Mon Jul 01, 2019 10:46 am
Posts: 24
Thank you it works. But new problem arrise causing virtualbox meditation (error hang). now, i can list the code what i got from james molloy.

descriptor_table.c
Code:
#include "common.h"
#include "descriptor_table.h"

struct gdt_entry_struct gdt_entries[5];
struct gdt_ptr_struct gdt_ptr;
struct idt_ptr_struct idt_ptr;
struct idt_entry_struct idt_entries[256];

extern void idt_flush(uint32_t);
extern void gdt_flush(uint32_t);

static void init_gdt();
static void init_idt();
static void gdt_set_gate(int32_t,uint32_t,uint32_t,uint8_t,uint8_t);
static void idt_set_gate(uint8_t,uint32_t,uint16_t,uint8_t);

void init_descriptor_tables() {
   init_gdt();
   init_idt();
}

static void init_gdt() {
    gdt_ptr.limit = (sizeof(struct gdt_entry_struct) * 5) - 1;
    gdt_ptr.base = (uint32_t)&gdt_entries;
    gdt_set_gate(0,0,0,0,0);
    gdt_set_gate(1,0,0xFFFFFFF,0x9A,0xCF);
    gdt_set_gate(2,0,0xFFFFFFF,0x92,0xCF);
    gdt_set_gate(3,0,0xFFFFFFF,0xFA,0xCF);
    gdt_set_gate(4,0,0xFFFFFFF,0xF2,0xCF);
    gdt_flush((uint32_t)&gdt_ptr);
}

static void gdt_set_gate(int32_t num,uint32_t base,uint32_t limit,uint8_t access,uint8_t granularity) {
    gdt_entries[num].base_low = (base & 0xFFFF);
    gdt_entries[num].base_middle = (base >> 16) & 0xFFFF;
    gdt_entries[num].base_high = (base >> 24) & 0xFFFF;
    gdt_entries[num].limit_low = (limit & 0xFFFF);
    gdt_entries[num].granularity = (limit >> 16) & 0x0F;
    gdt_entries[num].granularity |= granularity & 0x0F;
    gdt_entries[num].access = access;
}

static void init_idt() {
    idt_ptr.limit = sizeof(struct idt_entry_struct) * 256 - 1;
    idt_ptr.base = (uint32_t)&idt_entries;
    memset(&idt_entries,0,sizeof(struct idt_entry_struct) * 256);
    idt_set_gate( 0, (uint32_t)isr0 , 0x08, 0x8E);
    idt_set_gate( 1, (uint32_t)isr1 , 0x08, 0x8E);
    idt_set_gate( 2, (uint32_t)isr2 , 0x08, 0x8E);
    idt_set_gate( 3, (uint32_t)isr3 , 0x08, 0x8E);
    idt_set_gate( 4, (uint32_t)isr4 , 0x08, 0x8E);
    idt_set_gate( 5, (uint32_t)isr5 , 0x08, 0x8E);
    idt_set_gate( 6, (uint32_t)isr6 , 0x08, 0x8E);
    idt_set_gate( 7, (uint32_t)isr7 , 0x08, 0x8E);
    idt_set_gate( 8, (uint32_t)isr8 , 0x08, 0x8E);
    idt_set_gate( 9, (uint32_t)isr9 , 0x08, 0x8E);
    idt_set_gate(10, (uint32_t)isr10, 0x08, 0x8E);
    idt_set_gate(11, (uint32_t)isr11, 0x08, 0x8E);
    idt_set_gate(12, (uint32_t)isr12, 0x08, 0x8E);
    idt_set_gate(13, (uint32_t)isr13, 0x08, 0x8E);
    idt_set_gate(14, (uint32_t)isr14, 0x08, 0x8E);
    idt_set_gate(15, (uint32_t)isr15, 0x08, 0x8E);
    idt_set_gate(16, (uint32_t)isr16, 0x08, 0x8E);
    idt_set_gate(17, (uint32_t)isr17, 0x08, 0x8E);
    idt_set_gate(18, (uint32_t)isr18, 0x08, 0x8E);
    idt_set_gate(19, (uint32_t)isr19, 0x08, 0x8E);
    idt_set_gate(20, (uint32_t)isr20, 0x08, 0x8E);
    idt_set_gate(21, (uint32_t)isr21, 0x08, 0x8E);
    idt_set_gate(22, (uint32_t)isr22, 0x08, 0x8E);
    idt_set_gate(23, (uint32_t)isr23, 0x08, 0x8E);
    idt_set_gate(24, (uint32_t)isr24, 0x08, 0x8E);
    idt_set_gate(25, (uint32_t)isr25, 0x08, 0x8E);
    idt_set_gate(26, (uint32_t)isr26, 0x08, 0x8E);
    idt_set_gate(27, (uint32_t)isr27, 0x08, 0x8E);
    idt_set_gate(28, (uint32_t)isr28, 0x08, 0x8E);
    idt_set_gate(29, (uint32_t)isr29, 0x08, 0x8E);
    idt_set_gate(30, (uint32_t)isr30, 0x08, 0x8E);
    idt_set_gate(31, (uint32_t)isr31, 0x08, 0x8E);
    idt_flush((uint32_t)&idt_ptr);
}

static void idt_set_gate(uint8_t num,uint32_t base,uint16_t sel,uint8_t flags) {
    idt_entries[num].base_low = base & 0xFFFF;
    idt_entries[num].base_high = (base >> 16) & 0xFFFF;
    idt_entries[num].selector = sel;
    idt_entries[num].always_zero = 0;
    idt_entries[num].flags = flags | 0x60;
}


descriptor_table.h
Code:
#include <stdint.h>
struct gdt_entry_struct{
    uint16_t limit_low;
    uint16_t base_low;
    uint8_t base_middle;
    uint8_t access;
    uint8_t granularity;
    uint8_t base_high;
} __attribute__((packed));

struct gdt_ptr_struct {
    uint16_t limit;
    uint32_t base;
} __attribute__((packed));

struct idt_entry_struct {
    uint16_t base_low;
    uint16_t selector;
    uint8_t always_zero;
    uint8_t flags;
    uint16_t base_high;
} __attribute__((packed));

struct idt_ptr_struct {
   uint16_t limit;
   uint32_t base;
} __attribute__((packed));

void init_descriptor_tables();

extern void isr0();
extern void isr1();
extern void isr2();
extern void isr3();
extern void isr4();
extern void isr5();
extern void isr6();
extern void isr7();
extern void isr8();
extern void isr9();
extern void isr10();
extern void isr11();
extern void isr12();
extern void isr13();
extern void isr14();
extern void isr15();
extern void isr16();
extern void isr17();
extern void isr18();
extern void isr19();
extern void isr20();
extern void isr21();
extern void isr22();
extern void isr23();
extern void isr24();
extern void isr25();
extern void isr26();
extern void isr27();
extern void isr28();
extern void isr29();
extern void isr30();
extern void isr31();


Top
 Profile  
 
 Post subject: Re: Error compile GDT and Interrupt
PostPosted: Tue Jul 02, 2019 8:36 am 
Offline
Member
Member
User avatar

Joined: Fri Oct 27, 2006 9:42 am
Posts: 1925
Location: Athens, GA, USA
I try to get this out to all new members, to get everyone started on the same footing. I usually send it by email, but I think I will take this opportunity to repost it in the forum again. I hope this helps.
----------------------------------

The first thing I want to say is this: if you aren't already using version control for all software projects you are working on, drop everything and start to do that now. Set up a VCS such as Git, Subversion, Mercurial, Bazaar, or what have you - which you use is less important than the fact that you need to use it. Similarly, setting up your repos on an offsite host such as Gitlab, Github, Sourceforge, CloudForge, or BitBucket should be the very first thing you do whenever you start a new project, no matter how large or small it is.

If nothing else, it makes it easy to share your code with us on the forum, as you can just post a link, rather than pasting oodles and oodles of code into a post.

Once you have that out of the way (if you didn't already), you can start to consider the OS specific issues.

If you haven't already, I would strongly advise you to read the introductory material in the wiki:


After this, go through the material on the practical aspects of
running an OS-dev project:

I strongly suggest that you read through these pages in detail, along with the appropriate ones to follow, before doing any actual development. These pages should ensure that you have at least the basic groundwork for learning about OS dev covered.

This brings you to your first big decision: which platform, or platforms, to target. Commonly options include:
  • x86 - the CPU architecture of the stock PC desktops and laptops, and the system which remains the 'default' for OS dev on this group. However, it is notoriously quirky, especially regarding Memory Segmentation, and the sharp divisions between 16-bit Real Mode, 16-bit and 32-bit Protected Modes, and 64-bit Long Mode.
  • ARM - a RISC architecture widely used on mobile devices and for 'Internet of Things' and 'Maker' equipment, including the popular Raspberry Pi and Beagleboard single board computers. While it is generally seen as easier to work with that x86, most notably in the much less severe differences in between the 32-bit and 64-bit modes and the lack of memory segmentation, the wiki and other resources don't cover it nearly as well (though this is changing over time as it becomes more commonly targeted).
  • MIPS, another RISC design which is slightly older than ARM. It is one of the first RISC design to come out, being part of the reason the idea caught on, and is even simpler than ARM in terms of programming, though a bit tedious when it comes to assembly programming. While it was widely used in workstations and game consoles in the 1990s, it has declined significantly due to mismanagement by the owners of the design, and is mostly seen in devices such as routers. There are a handful of System on Chip single-board computers that use it, such as the Creator Board and the Onion Omega2, and manufacturers in both China and Russia have licensed the ISA with the idea of breaking their dependence on Intel. The ISA was made open-source in 2018, which may lead to more widespread use. Finding good information on the instruction set is easy, as it is widely used in courses on assembly language and computer architecture and there are several emulators that run MIPS code, but finding usable information on the actual hardware systems using it is often difficult at best.
  • RISC-V is an up and coming open source hardware ISA, closely related to MIPS in overall design, but so far is Not Ready For Prime Time. It is developing rapidly, however, and a handful of maker-grade SBCs using it have come on the market in 2018 and 2019.

You then need to decide which Languages to use for the kernel. For most OS-Developers this means knowing and using C; while other languages can be used, it is important to know how to read C code, even if you don't use C, as most OS examples are written in it. You will also need to know at least some assembly language for the target platform, as there are always parts of the kernel and the device drivers which cannot be done in high-level languages.

You further need to choose the compiler, assembler, linker, build tool, and support utilities to use - what is called the 'toolchain' for your OS. For most platforms, there aren't many to choose from, and the obvious choice would be GCC and the Binutils toolchain due to their ubiquity. However, on the Intel x86 platform, it isn't as simple, as there are several other toolchains which are in widespread use for it, the most notable being the Microsoft one - a very familiar one to Windows programmers, but one which presents problems in OSDev. The biggest issue with Visual Studio, and with proprietary toolchains in general, is that using it rules out the possibility of your OS being "self-hosting" - that is to say, being able to develop your OS in the OS itself, something most OSdevs do want to eventually be able to do. The fact that Porting GCC to your OS is feasible, whereas porting proprietary x86 toolchains isn't, is a big factor in the use Binutils and GCC, as it their deep connection to Linux and other Unix derivatives.

Regardless of the high-level language you use for OS dev (if any), you will still need to use assembly language, which means choosing an assembler. If you are using Binutils and GCC, the obvious choice would be GAS, but for x86 especially, there are other assemblers which many OSdevs prefer, such as Netwide Assembler (NASM) and Flat Assembler (FASM).

The important thing here is that assembly language syntax varies more among the x86 assemblers than it does for most other platforms, with the biggest difference being that between the Intel syntax used in the majority of x86 assemblers, and the AT&T syntax used in GAS. You can see an overview of the differences on the somewhat misnamed wiki page Opcode syntax. While it is possible to coax GAS to use the Intel syntax using the .intel_syntax noprefix directive, the opposite is generally not true for Intel-based assemblers such as NASM, and even with that directive, GAS is still quite different from other x86 assemblers in other regards.

It is still important to understand that the various Intel syntax assemblers - NASM, FASM, and YASM among others - have differences in how they handle indexing, in the directives they use, and in their support for features such as macros and defining data structures. While most of these follow the general syntax of Microsoft Assembler (MASM), they all diverge from it in various ways.

Once you know which platform you are targeting, and the toolchain you want to use, you need to understand them. You should read up on the core technologies for the platform. Assuming that you are targeting the PC architecture, this would include:

This leads to the next big decision: which Bootloader to use. There are a number of different standard bootloaders for x86, with the most prominent being GRUB. We strong recommend against Rolling Your Own Bootloader, but it is an option as well.

You need to consider what kind of File System to use. Common ones used when starting out in OS dev include:

We generally don't recommend designing your own, but as with boot loaders, it is a possibility as well.

While this is a lot of reading, it simply reflects the due diligence that any OS-devver needs to go through in order to get anywhere. OS development, even as a simple project, is not amenable to the Stack Overflow cut-and-paste model of software development; you really need to understand a fair amount of the concepts and principles before writing any code, and the examples given in tutorials and forum posts generally are exactly that. Copying an existing code snippet without at least a basic idea of what it is doing simply won't do. While learning itself is an iterative process - you learn one thing, try it out, see what worked and what didn't, read some more, etc. - in this case a basic foundation is needed at the start. Without a solid understanding of at least some of the core ideas before starting, you simply can't get very far in OS dev.

Hopefully, this won't scare you off; it isn't nearly as bad as it sounds. It just takes a lot of patience and a bit of effort, a little at a time.

_________________
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.


Top
 Profile  
 
 Post subject: Re: Error compile GDT and Interrupt
PostPosted: Tue Jul 02, 2019 1:11 pm 
Offline
Member
Member

Joined: Wed Dec 12, 2018 12:16 pm
Posts: 119
Another recomendation: You're in Windows 10, so instead of using Cygwin, is better to use WSL (Windows Subsystem for Linux). I use it, and no problems so far.


Top
 Profile  
 
 Post subject: Re: Error compile GDT and Interrupt
PostPosted: Fri Jul 05, 2019 8:06 am 
Offline

Joined: Mon Jul 01, 2019 10:46 am
Posts: 24
How about vagrant, can i use it?
Thank you Schol-R-LEA. Im trying your advice.


Top
 Profile  
 
 Post subject: Re: Error compile GDT and Interrupt
PostPosted: Fri Jul 05, 2019 11:04 am 
Offline
Member
Member
User avatar

Joined: Tue Oct 17, 2006 10:35 pm
Posts: 39
Location: Eagle, ID (USA)
Yes, you can use vagrant to setup a linux box and compile your own operating system just like you can with a docker image or a virtual machine with linux on it. While you wont have the issue with underscores on vagrant like you did with using cygwin since the file format will be elf and not pe. It is still recommended to setup a cross-compiler since the compiler on linux is compiled with more options than you want and you will need to pass some additional options to your makefile to make it work.

_________________
"I think it may be time for some guru meditation"
"Barbarians don't do advanced wizardry"


Top
 Profile  
 
 Post subject: Re: Error compile GDT and Interrupt
PostPosted: Tue Jul 23, 2019 7:27 am 
Offline

Joined: Mon Jul 01, 2019 10:46 am
Posts: 24
Sorry I've got some error. Guess what kind error is it in linker. I'm Frustrated.
Code:
i686-elf-gcc -T linker.ld -o myos.bin -ffreestanding -O2 -nostdlib kernel/kernel.o arch/x86/boot.o arch/x86/port.h driver/vga.o driver/vga.h  -lgcc
/home/ananta/opt/cross/lib/gcc/i686-elf/9.1.0/../../../../i686-elf/bin/ld: kernel/kernel.o: in function `kernel_main':
kernel.c:(.text+0x4): undefined reference to `vga_init'
/home/ananta/opt/cross/lib/gcc/i686-elf/9.1.0/../../../../i686-elf/bin/ld: kernel.c:(.text+0x11): undefined reference to `WriteScreen'
/home/ananta/opt/cross/lib/gcc/i686-elf/9.1.0/../../../../i686-elf/bin/ld: kernel.c:(.text+0x1d): undefined reference to `WriteScreen'
collect2: error: ld returned 1 exit status
Makefile:25: recipe for target 'myos.bin' failed
make: *** [myos.bin] Error 1


You can check my Makefile

Code:
GCCPARAMS = -std=gnu99 -ffreestanding -O2 -Wall -Wextra
NASMPARAMS = -felf32
GCC = i686-elf-gcc
AS = i686-elf-as
GCCLINKING = -ffreestanding -O2 -nostdlib

DRIVER_OBJS = $(patsubst %.c,%.o,$(wildcard driver/*.c))
DRIVER_OBJS += $(patsubst %.c,%.o,$(wildcard driver/*.h))

KERNEL_OBJS = $(patsubst %.c,%.o,$(wildcard kernel/*.c))
KERNEL_OBJS += $(patsubst %.s,%.o,$(wildcard arch/x86/*.s))
KERNEL_OBJS += $(patsubst %.s,%.o,$(wildcard arch/x86/*.h))
KERNEL_OBJS += $(DRIVER_OBJS)

kernel/%.o : kernel/%.c
   $(GCC) -c $< -o $@ $(GCCPARAMS)

arch/x86/%.o : arch/x86/%.s
   $(AS) $< -o $@

driver/%.o : driver/%.c 
   $(GCC) -c $< -o $@ $(GCCPARAMS)

myos.bin: linker.ld  $(KERNEL_OBJS)
   $(GCC) -T $< -o $@ $(GCCLINKING) $(KERNEL_OBJS)  -lgcc

myos.iso: myos.bin
   mkdir -p iso/boot/grub
   cp myos.bin iso/boot/myos.bin
   echo 'set timeout=0'> iso/boot/grub/grub.cfg
   echo 'set default=0' >> iso/boot/grub/grub.cfg
   echo ''
   echo 'menuentry "My Operating System" {' >> iso/boot/grub/grub.cfg
   echo '   multiboot /boot/myos.bin' >> iso/boot/grub/grub.cfg
   echo '  boot' >> iso/boot/grub/grub.cfg
   echo '}' >> iso/boot/grub/grub.cfg
   grub-mkrescue -o myos.iso iso
   rm -rf iso
run:
   export DISPLAY=:0
   qemu-system-i386 -cdrom myos.iso   

clean:
   # rm *\.bin
   rm kernel/*\.o
   rm arch/x86/*\.o
   rm driver/*\.o


arch/x86/boot.s
Code:
.set FLAGS, (1 << 0) | (1 << 1)
.set MAGIC, 0x1BADB002
.set CHECKSUM, -(MAGIC + FLAGS)

.section .multiboot
.align 4
   .long MAGIC
   .long FLAGS
   .long CHECKSUM

.section .bss
.align 16
stack_bottom:
.skip 16384
stack_top:

.section .text
.extern kernel_main
.global _start
.type _start, @function
_start:
      mov $stack_top,%esp
      call kernel_main
      cli
1:      hlt
      jmp 1b
.end:
.size _start, . - _start


arch/x86/port.h
Code:
#include <stdint.h>

inline void outb(uint16_t port,uint8_t value) {
    asm volatile ( "outb %0, %1" : : "a"(value), "Nd"(port) );
}

inline uint8_t inb(uint16_t port) {
    uint8_t ret;
    asm volatile("inb %1,%0;"
    : "=a" (ret)
    : "Nd"(port));
    return ret;
}

inline uint16_t inw(uint16_t port) {
    uint16_t ret;
    asm volatile("inw %1,%0;"
    : "=a"(ret)
    : "Nd"(port));
    return ret;
}



driver/vga.h
Code:
#include <stdint.h>
#include "../arch/x86/port.h"

static int cursor_x,cursor_y ;
static uint16_t* vga_memory = (uint16_t*)0xb8000;

enum VGA_COLOR {
    BLACK = 0,
    BLUE = 1,
    GREEN = 2,
    CYAN = 3,
    RED = 4,
    MAGENTA = 5,
    BROWN = 6,
    LIGHT_GRAY = 7,
    DARK_GRAY = 8,
    LIGHT_BLUE = 9,
    LIGHT_GREEN = 10,
    LIGTH_CYAN = 11,
    LIGHT_RED = 12,
    LIGHT_MAGENTA = 13,
    YELLOW = 14,
    WHITE = 15
};


static void ScrollScreen();
static void MoveCursor();
static void ClearScreen();
uint16_t FindCursor();
static void WriteScreen(const char *str);
static void vga_init();


driver/vga.c
Code:
#include "vga.h"

static void MoveCursor() {
    uint16_t position = cursor_y * 80 + cursor_x;
    outb(0x3D4,0x0F);
    outb(0x3D5,(uint8_t) (position & 0xFF));
    outb(0x3D4,0x0E);
    outb(0x3D5,(uint8_t)((position >> 8) & 0xFF));
}

static void ScrollScreen() {
    uint8_t attribute = (BLACK << 4) | (WHITE & 0x0F);
    char blank = 0x20 | (attribute << 8);
    if (cursor_y >= 25) {
        int j;
        for (j=80;j<24*80;j++)
            vga_memory[j] = vga_memory[j+80];
        for (j=24*80;j<25*80;j++)
            vga_memory[j] = blank;
    }
}

void WriteCharacter(enum VGA_COLOR backcolor, enum VGA_COLOR forecolor,char c) {
    uint16_t attribute = (backcolor << 4) | (forecolor & 0x0F);
    uint16_t *location;

    if (cursor_x >= 80) {
        cursor_x = 0;
        cursor_y++;
    }

    if (c == '\n') {
        cursor_x = 0;
        cursor_y++;
    } else if (c == 0x08 && cursor_x != 0) {
        cursor_x--;
    } else if (c == '\r') {
        cursor_x = 0;
    } else if (c == '\t') {
        cursor_x = (cursor_x + 8) & ~(8-1);
    } else {
        *location = vga_memory + (cursor_y * 80 + cursor_x);
        *location = c | attribute;
    }
    ScrollScreen();
    MoveCursor();
}

static void ClearScreen() {
    uint8_t attribute = (BLACK << 4) | (WHITE & 0x0F);
    char blank = 0x20 | (attribute << 8);
    for (int j=0*80;j<25*80;j++)
        vga_memory[j] = blank;
}

uint16_t FindCursor() {
    uint16_t position;
    outb(0x3D4,0x0F);
    position |= inb(0x3D5);
    outb(0x3D4,0x0E);
    position |= ((uint16_t)inb(0x3D5) << 8);
}

static void WriteScreen(const char *str) {
    for (int j=0;str[j] != '\0';j++)
        WriteCharacter(str[j],BLACK,WHITE);
}

static void vga_init() {
    ClearScreen();
    FindCursor();
}


kernel/main.c
Code:
#include "../driver/vga.h"

void kernel_main() {
    vga_init();
    WriteScreen("Hello World\n");
    WriteScreen("Hello This is my first OS\n");
}



Top
 Profile  
 
 Post subject: Re: Error compile GDT and Interrupt
PostPosted: Tue Jul 23, 2019 7:47 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5099
When you define a function with the "static" keyword, you can only use it in the code unit where you've defined it. For example:
Code:
static void vga_init() {...}

You define this function in vga.c, so you can't call it from anywhere else. If you want to call it from kernel.c, you must remove the "static" keyword.


Top
 Profile  
 
 Post subject: Re: Error compile GDT and Interrupt
PostPosted: Tue Jul 23, 2019 7:59 am 
Offline

Joined: Mon Jul 01, 2019 10:46 am
Posts: 24
Thank you I've finally found the solution


Top
 Profile  
 
 Post subject: Re: Error compile GDT and Interrupt
PostPosted: Sat Jul 27, 2019 10:33 am 
Offline

Joined: Mon Jul 01, 2019 10:46 am
Posts: 24
I'm sorry, i have alot question to ask especially gdt. What's wrong with my code, this code broke my virtualbox into "meditation guru" mode

gdt.c
Code:
#include "gdt.h"
extern void gdt_flush();
static void gdt_set_gate(int32_t,uint32_t,uint32_t,uint8_t,uint8_t);

struct gdt_entry gdt_entries[5];
struct gdt_ptr gdt_ptr;

void init_gdt() {
    gdt_ptr.limit = (sizeof(struct gdt_entry) * 5) - 1;
    gdt_ptr.base = (uint32_t)&gdt_entries;
    gdt_set_gate(0,0,0,0,0);
    gdt_set_gate(1,0,0xFFFFFFFF,0x9A,0xCF);
    gdt_set_gate(2,0,0xFFFFFFFF,0x92,0xCF);
    gdt_set_gate(3,0,0xFFFFFFFF,0xFA,0xCF);
    gdt_set_gate(4,0,0xFFFFFFFF,0xF2,0xCF);
    gdt_flush();
}

static void gdt_set_gate(int32_t num,uint32_t base,uint32_t limit,
uint8_t access,uint8_t granularity) {
    gdt_entries[num].base_low = (base & 0xFFFF);
    gdt_entries[num].base_middle = (base >> 16) & 0xFF;
    gdt_entries[num].base_high = (base >> 24) & 0xFF;

    gdt_entries[num].limit_low = (limit & 0xFFFF);
    gdt_entries[num].granularity = (limit >> 16) & 0x0F;

    gdt_entries[num].granularity |= granularity & 0x0F;
    gdt_entries[num].access = access;
}


gdt.h
Code:
#include <stdint.h>

struct gdt_entry {
    uint16_t limit_low;
    uint16_t base_low;
    uint8_t base_middle;
    uint8_t access;
    uint8_t granularity;
    uint8_t base_high;
};

struct gdt_ptr {
    uint16_t limit;
    uint32_t base;
};

void init_gdt();


gdt.S
Code:
.section .text
.align 4

.extern gdt_flush
.global gdt_flush
.type gdt_flush,@function

gdt_flush:
    mov 4(%esp),%eax
    lgdt (%eax)

    mov %ax, 0x10
    mov %ax, %ds
    mov %ax,%es
    mov %ax,%fs
    mov %ax,%ss
    mov %ax,%gs
    ljmp $0x08,$.flush

.flush:
    ret


Top
 Profile  
 
 Post subject: Re: Error compile GDT and Interrupt
PostPosted: Sat Jul 27, 2019 10:44 am 
Offline
Member
Member

Joined: Sat Jul 27, 2019 9:41 am
Posts: 25
Code:
extern void gdt_flush();


Code:
gdt_flush:
    mov 4(%esp),%eax
    lgdt (%eax)


What is gdt_flush loading into eax exactly? It doesn't have any parameters.


Top
 Profile  
 
 Post subject: Re: Error compile GDT and Interrupt
PostPosted: Sat Jul 27, 2019 10:56 am 
Offline

Joined: Mon Jul 01, 2019 10:46 am
Posts: 24
I have already changed my code but still get trouble in meditation mode

Code:
#include "gdt.h"

extern void gdt_flush(uint32_t);;
static void gdt_set_gate(int32_t,uint32_t,uint32_t,uint8_t,uint8_t);

struct gdt_entry gdt_entries[5];
struct gdt_ptr gdt_ptr;

void init_gdt() {
    gdt_ptr.limit = (sizeof(struct gdt_entry) * 5) - 1;
    gdt_ptr.base = (uint32_t)&gdt_entries;
    gdt_set_gate(0,0,0,0,0);
    gdt_set_gate(1,0,0xFFFFFFFF,0x9A,0xCF);
    gdt_set_gate(2,0,0xFFFFFFFF,0x92,0xCF);
    gdt_set_gate(3,0,0xFFFFFFFF,0xFA,0xCF);
    gdt_set_gate(4,0,0xFFFFFFFF,0xF2,0xCF);
    gdt_flush((uint32_t)&gdt_ptr);
}

static void gdt_set_gate(int32_t num,uint32_t base,uint32_t limit,
uint8_t access,uint8_t granularity) {
    gdt_entries[num].base_low = (base & 0xFFFF);
    gdt_entries[num].base_middle = (base >> 16) & 0xFF;
    gdt_entries[num].base_high = (base >> 24) & 0xFF;

    gdt_entries[num].limit_low = (limit & 0xFFFF);
    gdt_entries[num].granularity = (limit >> 16) & 0x0F;

    gdt_entries[num].granularity |= granularity & 0x0F;
    gdt_entries[num].access = access;
}


all code gdt.S and gdt.h still same


Top
 Profile  
 
 Post subject: Re: Error compile GDT and Interrupt
PostPosted: Sat Jul 27, 2019 3:24 pm 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 671
One thing I noticed at the start of gdt_flush is:
Code:
gdt_flush:
    mov 4(%esp),%eax
    lgdt (%eax)

    mov %ax, 0x10
In particular with at&t syntax source is first destination is second. And immediate values need a dollar ($) sign otherwise the value is considered a memory operand. Thus the instruction you wrote writes the 16-bit value in AX to memory address 0x10. You want:
Code:
mov $10, %ax
which moves the immediate value 10 into the AX register.


Top
 Profile  
 
 Post subject: Re: Error compile GDT and Interrupt
PostPosted: Sat Jul 27, 2019 7:34 pm 
Offline

Joined: Mon Jul 01, 2019 10:46 am
Posts: 24
I've changed mov instruction but still got problem guru meditation in virtual box. What's the problem?
Code:
.section .text
.align 4

.global gdt_flush
.type gdt_flush,@function

gdt_flush:
    mov 4(%esp),%eax
    lgdt (%eax)

    mov $0x10,%ax
    mov %ax,%ds
    mov %ax,%es
    mov %ax,%fs
    mov %ax,%ss
    mov %ax,%gs
    ljmp $0x08,$.flush

.flush:
    ret


if you want looking the code this is the web https://github.com/Ananta98/OSdev


Last edited by Ananta96 on Sun Jul 28, 2019 12:56 am, edited 1 time in total.

Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 33 posts ]  Go to page 1, 2, 3  Next

All times are UTC - 6 hours


Who is online

Users browsing this forum: Google [Bot], SemrushBot [Bot] and 78 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group