Autor Thema: [All In One]-Question lolxdfly  (Gelesen 22734 mal)

lolxdfly

  • Beiträge: 52
    • Profil anzeigen
Gespeichert
« am: 16. September 2013, 17:45 »
Hi,
danke erstmal an alle, die mir bis jetzt schon geholfen haben.
Da sich bei mir viele Fragen bezüglich des C++-Kernel anhäufen habe ich mal eine AllInOne-Question erstellt  :-D
Den Code hab ich aber größtenteils verstanden! Im momment ist der Kernel noch fast unverändert. Ich habe nur die stdint.h anstatt die types.h verwendent. Außerdem habe ich die newline-Escape-Sequenz(#n) hinzugefügt.
Ich habe ich 5 Fragen mit absteigender Priorität:

Frage 0: Gibt es irgendwo eine TuT-Reihe, wo ein C++-Kernel fortgesetzt und erklärt wird? Inaktiv

Frage 1: Wie kann man die Tastatur im Kernel nutzen? Gibt es vorgefertigte libs, die ich dafür verwenden kann?? Ich habe nur 1 TuT gefunden. Das war allerdings nur schwer zu verstehen... Gelöst!

Frage 2: Wie kann man Bilder anzeigen lassen/ einzelne Pixel färben? Ich habe es mit der Pixeltoaster-lib(systemunabhängig) versucht. Hat aber nur errors ausgespuckt. Inaktiv

Frage 3: Wie ist der QEMU-log zu verstehen? (http://pastebin.com/4vUfBPpr) Gelöst!

Frage 4: Wie kann man die Maus im Kernel nutzen? Ist nur nötig, wenn Frage 1+2 schon beantwortet wurden und funktionieren! Inaktiv
« Letzte Änderung: 21. January 2014, 17:35 von lolxdfly »

streetrunner

  • Beiträge: 67
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 16. September 2013, 19:35 »
Zu Frage 0: Wenn Tante Google da nichts findet, dürfte die Wahrscheinlichkeit eher gering sein. Außerdem hat es schon seine Gründe, warum man einen Kernel in C ohne die beiden + schreibt. Aber letztenendlich dürfte es kein Problem darstellen einen C-Kernel in C++ nachzuprogrammieren, der Code könnte sogar fast der selbe sein (es zwingt dich ja keiner dazu Klassen zu verwenden). Das einzige Problem das ich immo sehe ist dass der Inline-Assembler wegfällt, womit du diesen Code als Funktionen in eine eigene Datei stecken musst.

Zu Frage 1: Hier http://www.lowlevel.eu/wiki/Teil_5_-_Interrupts findest du Interrupts, und hier http://www.lowlevel.eu/wiki/Keyboard_Controller wie du den Tastatur-Controller benutzt. Wenn du dann noch die Foren-Suche benutzt solltest du alles beisammen haben um die Tastatur ans laufen zu bekommen.

Zu Frage 2: Um Pixel anzuzeigen kannst du dich entweder mit VESA rumärgern, welches nur so lala funktioniert aber einen riesen Aufwand bedeutet, oder einen Grafiktreiber schreiben, was noch wesentlich mehr Aufwand bedeutet.

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 16. September 2013, 19:47 »
Frage 3: Wie ist der QEMU-log zu verstehen? (http://pastebin.com/4vUfBPpr)

In dem speziellen Log steht nichts interessantes. Es sind darin zwei Registerdumps (SMM: enter und SMM: after RSM) aufgezeichnet, die QEMU immer beim Systemstart ausgibt. Da du anscheinend Interrupts noch deaktiviert hast, stehen darin keine weiteren Registerdumps. Das ändert sich später, wenn du IRQs aktivierst, die INT-Instruktion ausführst oder Exceptions aufgrund von Fehlern ausgelöst werden. Für die Fehlersuche könntest du dann daraus weitere Informationen gewinnen.
Dieser Text wird unter jedem Beitrag angezeigt.

lolxdfly

  • Beiträge: 52
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 16. September 2013, 19:55 »
Zu Frage 2: Um Pixel anzuzeigen kannst du dich entweder mit VESA rumärgern, welches nur so lala funktioniert aber einen riesen Aufwand bedeutet, oder einen Grafiktreiber schreiben, was noch wesentlich mehr Aufwand bedeutet.

Hab das hier gefunden:
//Pointer auf den Speicher
unsigned char* VGA = (unsigned char*) 0xA0000;

void setpixel(int x, int y, unsigned char color) {
  int offset;
  if(0 <= x && x < 320) {
    if(0 <= y && y < 200) {
      offset = 320*y + x;
      VGA[offset] = color;
    }
  }
}
Wäre auch zu schön gewesen hätte es funktioniert  :-)
Liegt es daran, dass ich in text mode und in 13h mode was machen wollte?


Zu Frage 0: Wenn Tante Google da nichts findet, dürfte die Wahrscheinlichkeit eher gering sein. Außerdem hat es schon seine Gründe, warum man einen Kernel in C ohne die beiden + schreibt. Aber letztenendlich dürfte es kein Problem darstellen einen C-Kernel in C++ nachzuprogrammieren, der Code könnte sogar fast der selbe sein (es zwingt dich ja keiner dazu Klassen zu verwenden). Das einzige Problem das ich immo sehe ist dass der Inline-Assembler wegfällt, womit du diesen Code als Funktionen in eine eigene Datei stecken musst.

Soll ich auf C umsteigen? Bis jetzt hatte ich mit C nur Probleme. Außerdem lernen wir in der Schule grade c++. Wobei wir da erstmal lernen was cin und cout ist -.-

TheThing

  • Beiträge: 105
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 16. September 2013, 20:47 »
Wäre auch zu schön gewesen hätte es funktioniert  :-)
Liegt es daran, dass ich in text mode und in 13h mode was machen wollte?
Das liegt daran, dass du Copy-Paste-gesündigt hast ;) Stell dir mal folgende Frage: Wieso hätte es funktionieren sollen? Du befindest dich im Textmodus und versuchst Pixel zu setzen.

Für Grafik gibt es eigentlich drei Möglichkeiten:
1. VGA: Nur geringe Auflösungen und wenige Farben, dafür aber (meines Wissens nach) problemlos aus dem Protected-Mode verwendbar da VGA-Hardware per I/O Ports angesteuert wird.
2. VBE (VESA Bios Extensions): Höhere Auflösungen und mehr Farben, unterstützt aber nicht immer alle möglichen Auflösungen (z.B. ist auf meinem Notebook die native Auflösung des Bildschirms nicht per VBE setzbar). Schwieriger zu benutzen, da die Verwendung im Real Mode vorgesehen war. Es gab zwar später ein Protected-Mode Interface, aber nach allem was ich bisher gehört habe war das auch nur halbgarer Käse.
3. Eigener Treiber: Extrem hoher Aufwand, dafür kann ein eigener Treiber dann alles unterstützen was die Hardware bietet. Aus Mangel an Dokumentation und Beispielcode extrem schwierig, und selbst große Projekte wie nouveau, die schon seit Jahren existieren und zu denen hunderte Menschen beigetragen haben, können die Hardware nicht komplett ausreizen.
Wobei, eine eingeschränkte vierte Möglichkeit gibts auch noch:
4. Emulator-Treiber: Fällt zwar eigentlich unter Nr.3, aber Treiber für emulierte Hardware sind deutlich einfacher zu schreiben. Vor einiger Zeit hab ich mal ein paar Minuten investiert und mir den BGA (Bochs Graphics Adaptor) angesehen, innerhalb von Minuten hatte ich bunte Pixel auf dem Bildschirm. Eine echt einfache Sache, aber dafür läufts halt nicht auf echter Hardware.

Aber an dieser Stelle noch einen Rat: Nicht zu früh an Grafik denken. Die buntesten Pixel bringen nichts wenn das OS dahinter nichts kann ;)

Soll ich auf C umsteigen? Bis jetzt hatte ich mit C nur Probleme. Außerdem lernen wir in der Schule grade c++. Wobei wir da erstmal lernen was cin und cout ist -.-
Diese Frage solltest du niemals einer anderen Person stellen, höchstens dir selbst. Benutz einfach die Sprache die dir am angenehmsten ist bzw. die deinen gesteckten Zielen dienlich ist. Wenn du bereits in C++ angefangen hast, warum solltest du in C neu anfangen? Auch mit C++ ist OS-dev möglich.
« Letzte Änderung: 16. September 2013, 20:53 von TheThing »

lolxdfly

  • Beiträge: 52
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 16. September 2013, 21:09 »
Wäre auch zu schön gewesen hätte es funktioniert  :-)
Liegt es daran, dass ich in text mode und in 13h mode was machen wollte?
Das liegt daran, dass du Copy-Paste-gesündigt hast ;) Stell dir mal folgende Frage: Wieso hätte es funktionieren sollen? Du befindest dich im Textmodus und versuchst Pixel zu setzen.

Nunja ich befinde mich ja nicht nur im Textmodus. Ich hab einmal den Textmodus zum Text-anzeigenlassen. Und einmal den 13h(VGA)-Modus indem ich versucht habe Pixel zu setzen. Ich dachte es wäre so wie in XNA(C#). Dort kann man einfach die Ebenden überschreiben.(Text und 3d-View) :-D Wie kann ich denn beides machen? Wenn ich nur 13h-Modus nehme kann ich ja kein Text mehr darstellen...
So so sieht meine Video.cpp aus:
#include "Video.h"

Video screen;

Video::Video()
  : m_videomem((uint16_t*) 0xB8000 ), m_off(0), m_pos(0), m_color(0x0700)
{
  //Bildschirm leeren
  clear();
}
 
 //Pointer auf den Speicher
unsigned char* VGA = (unsigned char*) 0xA0000;

void setpixel(int x, int y, unsigned char color) {
  int offset;
  if(0 <= x && x < 320) {
    if(0 <= y && y < 200) {
      offset = 320*y + x;
      VGA[offset] = color;
    }
  }
}
 
Video::~Video(){
}
 
void Video::clear(){
  // Füllen des Bildschirms mit Leerzeichen
  for(int i = 0;i < (80*25);i++)
    m_videomem[i] = (unsigned char)' ' | m_color;
 
  // Zurücksetzen der Textausgabe nach links oben
  m_pos = 0;
  m_off = 0;

  setpixel(10, 10, '4');
}
 
Video& Video::operator << (const char* s){
  // Für jedes einzelne Zeichen wird put() aufgerufen
  bool checkfores = false, draw = true;
  char es = '0';
  while (*s != '\0')
  {
draw = true;
    if(checkfores == true)
{
  es = *s;
}
if(es == 'n' && checkfores == true)
{
  m_off+=80; //newline
  m_pos=0;
  checkfores = false;
  draw = false;
}
    if(*s == '#')
    {
  checkfores = true;
    }
else if (*s != '#' && draw == true)
{
  put(*s);
}
*s++;
  }
  return *this;
}
 
Video& Video::operator << (color::type color){
  m_color = (static_cast<uint16_t>(color) << 8) | (m_color & 0xF000);
  return *this;
}
 
Video& Video::operator << (const background& color){
  m_color = (static_cast<uint16_t>(color.m_color) << 12) | (m_color & 0x0F00);
  return *this;
}
 
void Video::put(char c){
  // Wenn die Textausgabe den rechten...
  if(m_pos >= 80){ //Zeile voll
    m_pos = 0;
    m_off += 80;
  }
 
  // ...oder den unteren Bildschirmrand erreicht, gibt es
  // einen Umbruch bzw. es wird aufgeräumt.
  if(m_off >= (80*25)) //Bildschirm voll
    clear();
 
  // Setzen des Zeichens und der Farbe in den Videospeicher
  m_videomem[m_off + m_pos] = (uint16_t)c | m_color;
  m_pos++;
}
Die Video.h kannst du aus http://www.lowlevel.eu/w/index.php?title=C%2B%2B-Kernel_mit_GRUB&oldid=11074#Kernel nehmen.
« Letzte Änderung: 16. September 2013, 21:13 von lolxdfly »

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 16. September 2013, 21:27 »
Nunja ich befinde mich ja nicht nur im Textmodus. Ich hab einmal den Textmodus zum Text-anzeigenlassen. Und einmal den 13h(VGA)-Modus indem ich versucht habe Pixel zu setzen. Ich dachte es wäre so wie in XNA(C#). Dort kann man einfach die Ebenden überschreiben.(Text und 3d-View) :-D

So ist es aber nicht. Entweder Textmodus oder Grafikmodus. Wenn du Text im Grafikmodus darstellen willst, musst du die Zeichen Pixel für Pixel malen. Pixelgrafik im Textmodus ist nicht möglich. Du musst also zunächst in den Grafikmodus schalten, wenn du das haben willst.
Dieser Text wird unter jedem Beitrag angezeigt.

lolxdfly

  • Beiträge: 52
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 16. September 2013, 21:51 »
So ist es aber nicht. Entweder Textmodus oder Grafikmodus. Wenn du Text im Grafikmodus darstellen willst, musst du die Zeichen Pixel für Pixel malen. Pixelgrafik im Textmodus ist nicht möglich. Du musst also zunächst in den Grafikmodus schalten, wenn du das haben willst.

Das heißt, dass wenn ich auch nur einen Mauszeiger machen will, muss jeden einzelnen Buchstaben mit jedem einelnem Pixel setzen  :-o
Ich glaube fange dann doch erst mit der Tastatur an  :|

Svenska

  • Beiträge: 1 790
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 16. September 2013, 23:00 »
Hallo,

Frage 0: Gibt es irgendwo eine TuT-Reihe, wo ein C++-Kernel fortgesetzt und erklärt wird?
Eher nicht. Tutorials bringen etwas bis zu dem Punkt, wo das Zusammenspiel aus Compiler, Linker, Umgebung und Emulator soweit läuft, dass der Startup-Code zuverlässig funktioniert plus ein kleines bisschen mehr (Textausgabe, Interrupts, Tastatur) zur Demonstration. Alles, was darüber hinaus geht, kann dir von einem Tutorial nicht abgenommen werden, weil es sehr stark vom Kernel selbst abhängt.

Frage 1: Wie kann man die Tastatur im Kernel nutzen? Gibt es vorgefertigte libs, die ich dafür verwenden kann?? Ich habe nur 1 TuT gefunden. Das war allerdings nur schwer zu verstehen...
Ab diesem Punkt bist du selbst auf dich gestellt. Was du dann in großen Mengen benutzen möchtest, sind die originalen Datenblätter oder aufbereitete Hardwarebeschreibungen (siehe hier im Wiki). Du musst lernen, aus dem "aha, so funktioniert die Tastatur" den passenden Code zu erzeugen, um sie passend anzusteuern (Treiber) und sie den Anwendungen zur Verfügung zu stellen.

Frage 2: Wie kann man Bilder anzeigen lassen/ einzelne Pixel färben?
Dazu brauchst du einen Grafiktreiber. Allerdings, wie schon geschrieben, verlierst du damit den Textmodus: Alles oder nichts. (Wobei es nicht besonders schwer ist, eine Textausgabe in einem Grafikmodus herzustellen. Es ist nur deutlich langsamer.)

Frage 4: Wie kann man die Maus im Kernel nutzen? Ist nur nötig, wenn Frage 1+2 schon beantwortet wurden und funktionieren!
Ähnlich wie die Tastatur, zumindest gilt das bei PS/2-Tastaturen und PS/2-Mäusen. Serielle und USB-Mäuse funktionieren wieder anders.

Gruß,
Svenska

lolxdfly

  • Beiträge: 52
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 17. September 2013, 16:37 »
Hallo,
ich habe den Kernel abgeändert, sodass er VGA nutzt und eigentlich ein Pixel der Position x=10 und y=10 blau färben müsste. Nun tut er dies leider nicht. Es kommt einfach ein schwarzer Bildschirm, wo nur steht, dass das BIOS geladen wurde. Der QEMU-log ist genauso wie vorher! Das Compilen ging fehlerfrei. Es gabe lediglich 3 warnungen auf unbenutze Werte. Das ist aber normal. Ich hoffe ihr könnt mir noch einmal helfen. Solbalt ich ein pixel erfolgreich gefärbt habe komme ich vorerst alleine weiter. Hier mein Code:

asmKernel.asm:
global loader ; Unser Einsprungspunkt
extern kernelMain ; kernelMain() aus Kernel.cpp
extern initialiseConstructors ; aus Startup.cpp
 
FLAGS    equ 0
MAGIC    equ 0x1BADB002 ; Magicnumber - Erkennungsmerkmal für GRUB
CHECKSUM equ -(MAGIC + FLAGS) ; Checksum
 
section .text
align 4
MultiBootHeader:
  dd MAGIC        ; Magic number
  dd FLAGS        ; Flags
  dd CHECKSUM    ; Checksum
 
loader:
  mov esp,0x200000 ; Stack an die 2MB-Grenze platzieren
  push eax          ; Multiboot-Magicnumber auf den Stack legen
  push ebx          ; Adresse der Multiboot-Structure auf den Stack legen
  call initialiseConstructors    ; Konstruktoren aufrufen
  call kernelMain      ; kernelMain aufrufen
 
stop:
  jmp stop

Kernel.cpp:
// Einbinden unseres Header
#include "Video.h"
#include "Multiboot.h"
#include "stdio.h"
 
extern "C" void kernelMain(const Multiboot& multiboot_structur,
                           uint32_t multiboot_magic);
 
void kernelMain(const Multiboot& multiboot_structur,
                uint32_t multiboot_magic)
{
  if (multiboot_magic != MULTIBOOT_MAGIC)
  {
    // Fehler!
//screen << background(color::light_gray) << color::blue << "Loading BOS(S)-Kernel...";
    return;
  }

}

link.txt:
ENTRY(loader)
OUTPUT_FORMAT(elf32-i386)
OUTPUT_ARCH(i386:i386)

SECTIONS
{
  . = 0x0100000;

  .text :
  {
    *(.text*)
    *(.rodata)
  }

  .data  :
  {
    start_ctors = .;
    *(.ctors)
    end_ctors = .;

    *(.data)
  }

  .bss  :
  {
    *(.bss)
  }

  /DISCARD/ : { *(.dtors) *(.comment) }
}

Multiboot.h:
#ifndef MULTIBOOT_H
#define MULTIBOOT_H
 
#include "stdint.h"
 
#define MULTIBOOT_MAGIC 0x2BADB002
 
struct Multiboot
{
  uint32_t flags;
  uint32_t mem_lower;
  uint32_t mem_upper;
  uint32_t bootdevce;
  uint32_t cmdline;
  uint32_t module_count;
  uint32_t module_address;
  /* etc... */
} PACKED;
 
#endif

Startup.cpp:
typedef void (*constructor)();
 
// Im Linkerskript definiert
extern "C" constructor start_ctors;
extern "C" constructor end_ctors;
 
extern "C" void initialiseConstructors();
 
// Ruft die Konstruktoren für globale/statische Objekte auf
void initialiseConstructors()
{
  for (constructor* i = &start_ctors;i != &end_ctors;++i)
    (*i)();
}

stdint.h:
/* ISO C9x  7.18  Integer types <stdint.h>
 * Based on ISO/IEC SC22/WG14 9899 Committee draft (SC22 N2794)
 *
 *  THIS SOFTWARE IS NOT COPYRIGHTED
 *
 *  Contributor: Danny Smith <danny_r_smith_2001@yahoo.co.nz>
 *
 *  This source code is offered for use in the public domain. You may
 *  use, modify or distribute it freely.
 *
 *  This code is distributed in the hope that it will be useful but
 *  WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
 *  DISCLAIMED. This includes but is not limited to warranties of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 *  Date: 2000-12-02
 */


#ifndef _STDINT_H
#define _STDINT_H
#define __need_wint_t
#define __need_wchar_t
#include <stddef.h>

/* 7.18.1.1  Exact-width integer types */
typedef signed char int8_t;
typedef unsigned char   uint8_t;
typedef short  int16_t;
typedef unsigned short  uint16_t;
typedef int  int32_t;
typedef unsigned   uint32_t;

/* 7.18.1.2  Minimum-width integer types */
typedef signed char int_least8_t;
typedef unsigned char   uint_least8_t;
typedef short  int_least16_t;
typedef unsigned short  uint_least16_t;
typedef int  int_least32_t;
typedef unsigned   uint_least32_t;

/*  7.18.1.3  Fastest minimum-width integer types
 *  Not actually guaranteed to be fastest for all purposes
 *  Here we use the exact-width types for 8 and 16-bit ints.
 */
typedef signed char int_fast8_t;
typedef unsigned char uint_fast8_t;
typedef short  int_fast16_t;
typedef unsigned short  uint_fast16_t;
typedef int  int_fast32_t;
typedef unsigned  int  uint_fast32_t;

/* 7.18.1.4  Integer types capable of holding object pointers */

#ifndef _INTPTR_T_DEFINED
#define _INTPTR_T_DEFINED
#ifdef _WIN64
  typedef __int64 intptr_t;
#else
  typedef int intptr_t;
#endif
#endif

#ifndef _UINTPTR_T_DEFINED
#define _UINTPTR_T_DEFINED
#ifdef _WIN64
  typedef unsigned __int64 uintptr_t;
#else
  typedef unsigned int uintptr_t;
#endif
#endif

/* 7.18.2  Limits of specified-width integer types */
#if !defined ( __cplusplus) || defined (__STDC_LIMIT_MACROS)

/* 7.18.2.1  Limits of exact-width integer types */
#define INT8_MIN (-128)
#define INT16_MIN (-32768)
#define INT32_MIN (-2147483647 - 1)
#define INT64_MIN  (-9223372036854775807LL - 1)

#define INT8_MAX 127
#define INT16_MAX 32767
#define INT32_MAX 2147483647
#define INT64_MAX 9223372036854775807LL

#define UINT8_MAX 0xff /* 255U */
#define UINT16_MAX 0xffff /* 65535U */
#define UINT32_MAX 0xffffffff  /* 4294967295U */
#define UINT64_MAX 0xffffffffffffffffULL /* 18446744073709551615ULL */

/* 7.18.2.2  Limits of minimum-width integer types */
#define INT_LEAST8_MIN INT8_MIN
#define INT_LEAST16_MIN INT16_MIN
#define INT_LEAST32_MIN INT32_MIN
#define INT_LEAST64_MIN INT64_MIN

#define INT_LEAST8_MAX INT8_MAX
#define INT_LEAST16_MAX INT16_MAX
#define INT_LEAST32_MAX INT32_MAX
#define INT_LEAST64_MAX INT64_MAX

#define UINT_LEAST8_MAX UINT8_MAX
#define UINT_LEAST16_MAX UINT16_MAX
#define UINT_LEAST32_MAX UINT32_MAX
#define UINT_LEAST64_MAX UINT64_MAX

/* 7.18.2.3  Limits of fastest minimum-width integer types */
#define INT_FAST8_MIN INT8_MIN
#define INT_FAST16_MIN INT16_MIN
#define INT_FAST32_MIN INT32_MIN
#define INT_FAST64_MIN INT64_MIN

#define INT_FAST8_MAX INT8_MAX
#define INT_FAST16_MAX INT16_MAX
#define INT_FAST32_MAX INT32_MAX
#define INT_FAST64_MAX INT64_MAX

#define UINT_FAST8_MAX UINT8_MAX
#define UINT_FAST16_MAX UINT16_MAX
#define UINT_FAST32_MAX UINT32_MAX
#define UINT_FAST64_MAX UINT64_MAX

/* 7.18.2.4  Limits of integer types capable of holding
    object pointers */
#ifdef _WIN64
#define INTPTR_MIN INT64_MIN
#define INTPTR_MAX INT64_MAX
#define UINTPTR_MAX UINT64_MAX
#else
#define INTPTR_MIN INT32_MIN
#define INTPTR_MAX INT32_MAX
#define UINTPTR_MAX UINT32_MAX
#endif

/* 7.18.2.5  Limits of greatest-width integer types */
#define INTMAX_MIN INT64_MIN
#define INTMAX_MAX INT64_MAX
#define UINTMAX_MAX UINT64_MAX

/* 7.18.3  Limits of other integer types */
#define PTRDIFF_MIN INTPTR_MIN
#define PTRDIFF_MAX INTPTR_MAX

#define SIG_ATOMIC_MIN INTPTR_MIN
#define SIG_ATOMIC_MAX INTPTR_MAX

#define SIZE_MAX UINTPTR_MAX

#ifndef WCHAR_MIN  /* also in wchar.h */
#define WCHAR_MIN 0
#define WCHAR_MAX 0xffff /* UINT16_MAX */
#endif

/*
 * wint_t is unsigned short for compatibility with MS runtime
 */
#define WINT_MIN 0
#define WINT_MAX 0xffff /* UINT16_MAX */

#endif /* !defined ( __cplusplus) || defined __STDC_LIMIT_MACROS */


/* 7.18.4  Macros for integer constants */
#if !defined ( __cplusplus) || defined (__STDC_CONSTANT_MACROS)

/* 7.18.4.1  Macros for minimum-width integer constants

    Accoding to Douglas Gwyn <gwyn@arl.mil>:
"This spec was changed in ISO/IEC 9899:1999 TC1; in ISO/IEC
9899:1999 as initially published, the expansion was required
to be an integer constant of precisely matching type, which
is impossible to accomplish for the shorter types on most
platforms, because C99 provides no standard way to designate
an integer constant with width less than that of type int.
TC1 changed this to require just an integer constant
*expression* with *promoted* type."
*/

#define INT8_C(val) val
#define UINT8_C(val) val
#define INT16_C(val) val
#define UINT16_C(val) val

#define INT32_C(val) val
#define UINT32_C(val) val##U
#define INT64_C(val) val##LL
#define UINT64_C(val) val##ULL

/* 7.18.4.2  Macros for greatest-width integer constants */
#define INTMAX_C(val)  INT64_C(val)
#define UINTMAX_C(val) UINT64_C(val)

#endif  /* !defined ( __cplusplus) || defined __STDC_CONSTANT_MACROS */

#endif

Video.cpp:
#include "Video.h"

Video screen;

Video::Video()
  : m_videomem((uint16_t*) 0xA0000 ), m_color(0x0700)
{
  clear();
}
 
Video::~Video(){
}
 
void Video::clear(){
  setpixel(10, 10, color::blue);
}
 
Video& Video::operator << (const char* s){

  return *this;
}
 
Video& Video::operator << (color::type color){

  return *this;
}
 
Video& Video::operator << (const background& color){

  return *this;
}

void Video::setpixel(int x, int y, color::type color) {
  int offset;
  if(0 <= x && x < 320) {
    if(0 <= y && y < 200) {
      offset = 320*y + x;
      m_videomem[offset] = color;
    }
  }
}

Video.h:
#ifndef VIDEO_H
#define VIDEO_H
 
#include "stdint.h"
 
namespace color
{
  enum type
  {
    black         = 0x00,
    blue          = 0x01,
    green         = 0x02,
    cyan          = 0x03,
    red           = 0x04,
    magenta       = 0x05,
    brown         = 0x06,
    light_gray    = 0x07,
    dark_gray     = 0x08,
    light_blue    = 0x09,
    light_green   = 0x0A,
    light_cyan    = 0x0B,
    light_red     = 0x0C,
    light_magenta = 0x0D,
    yellow        = 0x0E,
    white         = 0x0F
  };
}
 
struct background
{
  inline background(color::type color)
    : m_color(color){}
 
  color::type m_color;
};
 
class Video
{
  public:
    // Konstruktor
    Video();
 
    // Destruktor
    ~Video();
 
    // Leeren des Bildschirms, die Größe beträgt 80x25 Zeichen
    void clear();
 
    // Textausgabe
    Video& operator << (const char* s);
 
    // Vordergrundfarbe setzen
    Video& operator << (color::type color);
 
    // Hintergrundfarbe setzen
    Video& operator << (const background& color);
 
    // Ausgabe eines einzelnen Zeichens
    void setpixel(int x, int y, color::type color);
 
  private:
    // Zeiger auf den Videospeicher
    uint16_t* m_videomem;
 
    // FB/BG-Farbe
    uint16_t m_color;
};
 
// Globale Instanz der Video-Klasse, Definition in Video.cpp
extern Video screen;
 
#endif
« Letzte Änderung: 17. September 2013, 16:40 von lolxdfly »

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 17. September 2013, 17:15 »
ich habe den Kernel abgeändert, sodass er VGA nutzt und eigentlich ein Pixel der Position x=10 und y=10 blau färben müsste.

Du hast das Wichtigste und Schwierigste vergessen: Den Grafikmodus zu aktivieren. Ich glaube das Konzept ist dir nicht ganz klar, deswegen werde ich das mal versuchen zu illustrieren. Wenn du in z. B. Windows in der Systemsteuerung die Bildschirmauflösung änderst, dann sendet der Grafiktreiber über die I/O-Schnittstelle Befehle an die Grafikkarte, die sie dazu veranlassen diese Änderung durchzuführen. Wenn du z. B. als Auflösung 1600x1200 wählst, werden andere Befehle an die Grafikkarte gesendet, als wenn du 1920x1080 wählst. Genauso gibts es Befehlsfolgen, die die Grafikkarte in den Textmodus versetzen oder in den 320x200 Grafikmodus. Je nach Modus, verwendet die Grafikkarte einen anderen Speicherbereich aus dem sie Daten für Darstellung ausliest. Für den Textmodus ist das 0xB8000, für 320x200 ist das 0xA0000 und für höhere Auflösungen wieder eine andere Adresse. Was aber nicht funktioniert ist einfach an diese Adressen Sachen zu schreiben und zu erwarten, dass Grafikkarte weiß, welche Auflösung, etc. sie verwenden soll. Der Grund dafür ist wie bereits erwähnt, dass du nicht die entsprechende Befehlssequenz an die Grafikkarte geschickt hast.

Wie TheThing weiter oben schon erwähnt hat, gibt es mehrere Möglichkeiten diese Befehlssequenz an die Grafikkarte zu schicken. Da du dich im Protected Mode befindest, musst du entweder selbst die Grafikkarte ansteuern oder in den Real Mode (bzw. VM86) wechseln und das BIOS dafür aufrufen. Ersteres ist kompliziert und sieht ungefähr so aus: http://files.osdev.org/mirrors/geezer/osd/graphics/modes.c (das ist natürlich Code für mehrere Auflösungen), und das zweite ist in etwa genauso kompliziert und sieht ungefähr so aus: http://git.tyndur.org/?p=tyndur.git;a=blob;f=src/kernel2/src/arch/i386/vm86.c;h=50cc9f3cb1bdbad78bd779459453cb4f0cea16ab;hb=HEAD

Du könntest versuchen die erste Möglichkeit umzusetzen und die modes.c auf einem modernen Compiler zu laufen zu bringen, oder du beschäftigst dich damit in deinem OS den VM86 zu implementieren (den verlinkten Code aus tyndur nicht kopieren). Von der Illusion, dass wir dir nur helfen müssen einen Pixel zu färben und dann kommst du schon weiter, solltest du dich trennen. Nicht nur hast du noch einiges vor dir, sondern du wirst noch auf viele weitere Hürden stoßen, und ohne dich mit den Grundlagen zu beschäftigen kommst du nicht weit. Wenn du hingegen nur eine grafische Oberfläche umsetzen willst, dann solltest du vielleicht kein OS schreiben, sondern auf einem anderen aufbauen (was spricht gegen XNA, wenn du das schon kannst?). Wenn du so wenig andere Betriebssysteme wie möglich zwischen dir und der Hardware haben willst, kannst du auch versuchen mit einer Bibliothek wie z. B. Allegro unter DOS deine Vorstellungen umzusetzen.

Edit: Sorry wenn das etwas harsch klang. Ich will dich nicht demotivieren. Aber ich will auch nicht um den heißen Brei reden und irgendwelche Illusionen aufbauen.
« Letzte Änderung: 17. September 2013, 17:27 von Jidder »
Dieser Text wird unter jedem Beitrag angezeigt.

lolxdfly

  • Beiträge: 52
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 17. September 2013, 17:35 »
ich habe den Kernel abgeändert, sodass er VGA nutzt und eigentlich ein Pixel der Position x=10 und y=10 blau färben müsste.

Du hast das Wichtigste und Schwierigste vergessen: Den Grafikmodus zu aktivieren. Ich glaube das Konzept ist dir nicht ganz klar, deswegen werde ich das mal versuchen zu illustrieren. Wenn du in z. B. Windows in der Systemsteuerung die Bildschirmauflösung änderst, dann sendet der Grafiktreiber über die I/O-Schnittstelle Befehle an die Grafikkarte, die sie dazu veranlassen diese Änderung durchzuführen. Wenn du z. B. als Auflösung 1600x1200 wählst, werden andere Befehle an die Grafikkarte gesendet, als wenn du 1920x1080 wählst. Genauso gibts es Befehlsfolgen, die die Grafikkarte in den Textmodus versetzen oder in den 320x200 Grafikmodus. Je nach Modus, verwendet die Grafikkarte einen anderen Speicherbereich aus dem sie Daten für Darstellung ausliest. Für den Textmodus ist das 0xB8000, für 320x200 ist das 0xA0000 und für höhere Auflösungen wieder eine andere Adresse. Was aber nicht funktioniert ist einfach an diese Adressen Sachen zu schreiben und zu erwarten, dass Grafikkarte weiß, welche Auflösung, etc. sie verwenden soll. Der Grund dafür ist wie bereits erwähnt, dass du nicht die entsprechende Befehlssequenz an die Grafikkarte geschickt hast.

Wie TheThing weiter oben schon erwähnt hat, gibt es mehrere Möglichkeiten diese Befehlssequenz an die Grafikkarte zu schicken. Da du dich im Protected Mode befindest, musst du entweder selbst die Grafikkarte ansteuern oder in den Real Mode (bzw. VM86) wechseln und das BIOS dafür aufrufen. Ersteres ist kompliziert und sieht ungefähr so aus: http://files.osdev.org/mirrors/geezer/osd/graphics/modes.c (das ist natürlich Code für mehrere Auflösungen), und das zweite ist in etwa genauso kompliziert und sieht ungefähr so aus: http://git.tyndur.org/?p=tyndur.git;a=blob;f=src/kernel2/src/arch/i386/vm86.c;h=50cc9f3cb1bdbad78bd779459453cb4f0cea16ab;hb=HEAD

Du könntest versuchen die erste Möglichkeit umzusetzen und die modes.c auf einem modernen Compiler zu laufen zu bringen, oder du beschäftigst dich damit in deinem OS den VM86 zu implementieren (den verlinkten Code aus tyndur nicht kopieren). Von der Illusion, dass wir dir nur helfen müssen einen Pixel zu färben und dann kommst du schon weiter, solltest du dich trennen. Nicht nur hast du noch einiges vor dir, sondern du wirst noch auf viele weitere Hürden stoßen, und ohne dich mit den Grundlagen zu beschäftigen kommst du nicht weit. Wenn du hingegen nur eine grafische Oberfläche umsetzen willst, dann solltest du vielleicht kein OS schreiben, sondern auf einem anderen aufbauen (was spricht gegen XNA, wenn du das schon kannst?). Wenn du so wenig andere Betriebssysteme wie möglich zwischen dir und der Hardware haben willst, kannst du auch versuchen mit einer Bibliothek wie z. B. Allegro unter DOS deine Vorstellungen umzusetzen.

Edit: Sorry wenn das etwas harsch klang. Ich will dich nicht demotivieren. Aber ich will auch nicht um den heißen Brei reden und irgendwelche Illusionen aufbauen.

Puhh... Die modes.c ist ziemlich groß! und ziemlich kompliziert. Hmm mal sehen ob da was von verstehen kann. Ich gehe auch nochmal die Grundlagen durch.
Gegen XNA spricht im Grunde nichts. Ich habe ein EgoShooter fast komplett hinbekommen. Nur habe ich nicht die Zeit und die Lust alles mit blender zu designen.
 
Edit: Da ich nächste Woche 3 Klausuren schreibe (auch Informatik :-)) hab ich nicht so viel Zeit. Deswegen werde ich mich nach den Grundlage im Textmode an die Tastaturunterstützung setzen.
« Letzte Änderung: 17. September 2013, 18:03 von lolxdfly »

Svenska

  • Beiträge: 1 790
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 17. September 2013, 23:21 »
Hallo,

Puhh... Die modes.c ist ziemlich groß! und ziemlich kompliziert. Hmm mal sehen ob da was von verstehen kann.
Frage mal die Entwickler, die Grafiktreiber für aktuelle Grafikkarten und Smartphones schreiben. Deren Aussage ist, dass es derzeit kein komplizierteres Gerät als eine GPU gibt. (Und die haben in der Regel auch schon Erfahrung mit anderen Treibern.) Dagegen ist VGA noch recht gemütlich.

Wie ich bereits schrieb, beschäftige dich weniger mit Tutorials und Anleitungen und mehr mit Datenblättern oder aufbereiteten Spezifikationen. OS-Entwicklung beschäftigt sich hauptsächlich damit, Treiber für verschiedene Hardware (inklusive der CPU) zu schreiben und eine Umgebung zu schaffen, in der dann Anwendungen laufen.

Grafische Benutzeroberflächen gehören da normalerweise nicht dazu. (Auch unter Windows wird der Desktop von "explorer.exe" bereitgestellt und nicht vom NT-Kernel.) Wenn es dir eher darum geht, solltest du eher einen funktionierenden Kernel nehmen, der einen funktionierenden Grafiktreiber hat, und damit arbeiten.

Noch was: Mit einer direkten Ansteuerung von VGA-Karten bist du auf 640x480 (16 Farben) oder 320x200 (256 Farben) beschränkt. Mehr bietet auch die modes.c nicht. Mit VESA kannst du immerhin alles nutzen, was das Grafik-BIOS anbietet, aber dafür solltest du den Real Mode (oder VM86) nutzen. Beide Ansätze sind ziemlich langsam. Alles, was darüber hinausgeht, ist effektiv nicht machbar.

Gruß,
Svenska

lolxdfly

  • Beiträge: 52
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 26. September 2013, 19:55 »
Hi,
habe in den vergangeden Tagen den Tastatursupport fast komplett selbst hinbekommen  :-). Ich lese den port 0x60 aus und übersetze den Scancode mittels einer Header-Datei in Charwerte.
Es werden mittlerweile alle Tasten außer ä,ö,ü,ß,´,Shift, Tab, [Pfleiltasten],[PageUp, Einfg...] unterstützt! Wie ich das mit Shift und Tab hinbekomme weiß ich bereits, aber bei den Umlauten hab
ich keine Ahnung wie ich das angehen soll. Im I-net stand da auch nichts zu. Das größere Problem ist allerdings, das manche Tasten mehrere Scancodes haben(so meine Vermutung :-D).
Wenn ich z.B. - drücke printet er -/ . Das gleiche passiert, wenn ich /(auf Numpad) drücke. Wenn ich aber das Minus auf dem Numpad drücke kommt auch nur ein minus.
Ein weiteres Beispiel ist PageUp. Dann printet er eine 9. Wenn ich dem Scancode 201 noch nur zum Test # zuweise, printet er 9 und #.
Das ist die Codestelle zu dem -:
        // unsigned char c = Scancode aus Wertübergabe
else if(c==53 || c==74) //Scancodeabfrage (normal || numpad)
{
c1='-'; //Charwert zuweisen
}
Ich weiß, dass es besser ist, wenn man es mit einem Array löst. Das kommt noch...
« Letzte Änderung: 26. September 2013, 19:58 von lolxdfly »

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 26. September 2013, 20:03 »
Ich glaube du hast das Konzept von Make- und Breakcodes nicht richtig umgesetzt. Scancode 201 existiert nicht, sondern dass ist der Breakcode von 73, da 73 + 128 = 201. Die Scancodes von 0-127 heißen "make codes", und werden gesendet, wenn die Taste gedrückt wurde. Die Scancodes 128-255 heißen "break codes" und werden gesendet, wenn die Taste wieder losgelassen wurde. Das heißt die make codes sollten (fürs erste) bei dir veranlassen, dass das Zeichen ausgegeben wurde, und die break codes sollten nichts tun (außer du hast damit kompliziertes vor).
Dieser Text wird unter jedem Beitrag angezeigt.

streetrunner

  • Beiträge: 67
    • Profil anzeigen
Gespeichert
« Antwort #15 am: 26. September 2013, 20:27 »
Es kommt mir so vor als ob du über das amerikanische Tastatur-Layout stolperst. Da gibt es keine Umlaute, da diese halt im Englischen nicht vorkommen. Dafür sind diese Tasten mit anderen Zeichen belegt, das gilt auch für etliche andere Tasten (das y und z vertauscht sind ist da nur die Spitze des Eisbergs). Was du auf deiner Tastatur siehst ist das Deutsche Layout, aber deine Tastatur weiß davon natürlich nichts, sie sendet weiterhin die Englischen Codes.

Svenska

  • Beiträge: 1 790
    • Profil anzeigen
Gespeichert
« Antwort #16 am: 27. September 2013, 04:21 »
Was du auf deiner Tastatur siehst ist das Deutsche Layout, aber deine Tastatur weiß davon natürlich nichts, sie sendet weiterhin die Englischen Codes.
Jaein: Es gibt keine englischen oder deutschen Codes. Die Tastatur sendet Scancodes für die Tasten, nicht für deren Bedeutung. Einen Sinn aus den Tastendrücken musst du selbst rauslesen. Darum ist es ziemlich sinnvoll, die (tastaturabhängigen*) Scancodes erst in (tastaturunabhängige) Tastencodes umzusetzen und erst danach mit einem Tastaturlayout ein Zeichen zuzuweisen (sofern es eins gibt - F2 hat eher keins, ist aber trotzdem eine Taste).

* Die 105-Tasten-PC-Tastatur ist zwar standardisiert, aber Sondertasten wie "Play/Pause", "Browser öffnen" u.ä. sind unterschiedlich.

lolxdfly

  • Beiträge: 52
    • Profil anzeigen
Gespeichert
« Antwort #17 am: 29. September 2013, 14:09 »
Ich glaube du hast das Konzept von Make- und Breakcodes nicht richtig umgesetzt. Scancode 201 existiert nicht, sondern dass ist der Breakcode von 73, da 73 + 128 = 201. Die Scancodes von 0-127 heißen "make codes", und werden gesendet, wenn die Taste gedrückt wurde. Die Scancodes 128-255 heißen "break codes" und werden gesendet, wenn die Taste wieder losgelassen wurde. Das heißt die make codes sollten (fürs erste) bei dir veranlassen, dass das Zeichen ausgegeben wurde, und die break codes sollten nichts tun (außer du hast damit kompliziertes vor).
Ok. Aber wie kann ich jetzt Make- und Breakcode unterscheiden? Lässt sich der Breakcode irgendwie identifizieren?

 Ich habe erstmal den / entfernt. Wenn ich - gedrückt halte macht er ein Minus. Wenn ich / gredückt halte macht er ganz viel Minus. Das heiß er nimmt bei beiden den Makecode. Nur nimmt er den bei - nur einmal und bei / unendlich.  :?

Wenn ich z.B. das l auf 166 setzte, dann setzt er auch nur ein l wenn ich die Taste auch loslasse. (so wie es soll)

Svenska

  • Beiträge: 1 790
    • Profil anzeigen
Gespeichert
« Antwort #18 am: 29. September 2013, 15:21 »
Aber wie kann ich jetzt Make- und Breakcode unterscheiden? Lässt sich der Breakcode irgendwie identifizieren?
Wenn der Scancode kleiner als 128 ist, ist es ein Make-Code, sonst ist es ein Break-Code (für die Taste "Scancode-128").

lolxdfly

  • Beiträge: 52
    • Profil anzeigen
Gespeichert
« Antwort #19 am: 29. September 2013, 15:53 »
Da hätte ich auch drauf kommen können  :-)
Aber in meiner ScConverter.h ist mein höchster Wert 86. Also habe ich noch nie was mit dem Breakcode gemacht. Trotzdem habe ich das Problem mit dem - und /(man drückt / und es kommt -). Was vielleicht wichtig zu erwähnen ist: am Ende habe ich in der ScConverter.h:
else
c1='\0';
und in der Video.cpp:
    key=inb(0x060);
    final_key=SC2Char(key); //ScanCode in Char
    if(oldkey!=key && final_key!='\0'){
      put(final_key);
    }

Die Scancodes habe ich von http://www.blitzforum.de/help/Scancodes
Stimmt mit denen was nicht?
« Letzte Änderung: 29. September 2013, 15:54 von lolxdfly »

 

Einloggen