VGA-Programmierung.

Diskussion zum Thema Programmierung unter DOS (Intel x86)
Benutzeravatar
oDOSseus
LAN Manager
Beiträge: 239
Registriert: Di 10. Aug 2010, 15:21

VGA-Programmierung.

Beitrag von oDOSseus »

Hallo alle zusammen =)!

Ich programmiere grade auf ner VGA karte im mode 13h. Meine IDE (und compiler) ist Borland Turbo C++ 3.0 und es funktioniert alles super.
Ich habe schon ein Bildformat entwickelt, das super klappt, nur habe ich ein problem:
Die Textausgabe.
Mit 320x200 pixeln ist Text ja sowieso so eine sache. Aber was klar ist: die 8x9 Rasterfont wird es nicht sein, was ich nutzen möchte.
Ich habe schon ein paar Buchstaben erstellt/gemalt. Diese habe ich in einzelne Bilddateien gespeichert (mit dem von mir entwickelten Format das sehr wenig speicherplatz braucht).
Jetzt ist meine Frage:
Hat das BIOS irgendeine font die dazu nützlich ist oder muss ich erst eine Bilddatei schreiben, die alle Buchstaben enthält (kann ja schlecht für jeden Buchstaben ne Datei erstellen) und dann noch eine Routine zum lesen dieser font-Datei und zum speichern der Buchstaben in der RAM.
Und wenn ich das muss, gibt es dazu irgendein tutorial?
Ich kann einfach nichts finden.

Ich freue mich schon auf eure Antworten!
DOSferatu
DOS-Übermensch
Beiträge: 1220
Registriert: Di 25. Sep 2007, 12:05
Kontaktdaten:

Re: VGA-Programmierung.

Beitrag von DOSferatu »

Ich mache sowas schon seit Jahren und ja, im Grafikmodus muß man jeden Pixel der Buchstaben selbst setzen.
Die "normalen" BIOS-Zeichensätze haben eine Breite von 8 Pixeln und eine Höhe zwischen 1 und 32 Zeilen. (Wobei eigentlich in der Regel nur 8x8, 8x16 oder für diesen 43-Zeilen Mode auch 8x14 Zeichensätze benutzt werden.)
So ein "normaler" Zeichensatz ist so aufgebaut, daß jede Zeile ein Byte hat, die einzelnen Bits bestimmen, ob ein Pixel gesetzt (1) oder frei (0) ist, dabei ist das oberste Bit (also 128) der linke Pixel.
Der 9. Pixel wird nicht im Zeichensatz mitgespeichert. Ob der 9. Pixel gesetzt wird oder nicht, wird so entschieden:
Wenn das Zeichen die Nummern 192 bis 223 hat (also seine Nummer binär 110xxxxx ist), dann ist der 9. Pixel gleich dem 8. Pixel. Anderenfalls ist der 9. Pixel immer frei (also Hintergrund).

Man kann sich aber natürlich auch eigene Zeichensatz-Formate bauen. Sollten diese aber monochrom sein (nur 2 Farben, Zeichenfarbe und Hintergrundfarbe), dann ist es am besten, ebenfalls bit-basiert vorzugehen). Ich entwickle öfters mal solche "normalen" Zeichensätze (meistens 8x8) und speichere sie im selben Format wie die aus dem BIOS. Dabei hat ein Zeichensatz genau 2048 Bytes (2 kByte), nämlich 256*8. (256 Zeichen, 8 Bytes pro Zeichen). Habe aber auch schon 8*16er Zeichensätze gebaut.
Will sagen: Nein, man muß nicht 256 Files anlegen. Man kann auch alle Zeichen in einem Zeichensatz-File speichern.

Ich habe noch ein anderes Format entwickelt, das die Zeichen "senkrecht" speichert - d.h. sie haben alle die gleiche Höhe, aber können unterschiedliche Breiten haben - das dient dazu, "proportionale" Zeichen zu benutzen (also wo z.B. das i schmal ist und das W breit usw.)

Wie man das ganze darstellt, bleibt ja jedem selbst überlassen. Wenn Interesse, könnte ich mal eine kleine Subroutine schreiben, um Zeichen an jede Position im 320x200 Mode (Mode 13h) zu setzen, ausgehend von einem 8x8 Zeichensatz.

Ich habe hier auch (für mich selber) so Entwicklungs-Tools für Zeichensätze geschrieben. Eins für 8x8 Zeichensätze im obengenannten Format und eins für sowohl 8xIrgendwas Zeichensätze im "BIOS" Format, das aber auch proportionale Zeichensätze in meinem eigenen Format speichern kann. (Da gibt es mittlerweile zwei Formate, eins davon kann 4-farbige Zeichen generieren.)
Diese Tools sind aber... naja, voller Hotkeys und freakig zu bedienen. Wer Windows und Mausklickerei gewöhnt ist, wird sich damit etwas schwer tun...

Was Grafikprogrammierung im Allgemeinen angeht (Hercules, CGA, EGA, VGA und VESA), hab ich schon so ziemlich alles gemacht, was damit zu machen geht. (Auch diesen Mode X und eigene Auflösungen usw. - Mode X steuert sich halt geringfügig schwieriger an als der Mode 13h, aber dafür kann man auch in VGA damit höhere Auflösungen oder mehrere Bildseiten bekommen...)

Ich hab auf meine Webseite auch einige Tutorials geschrieben, aber der Text "Wie funktioniert Grafik?" setzt an einigen Stellen geringfügige Assembler-Kenntnisse voraus. Aber da beschreibe ich auch den Aufbau der verschiedenen Grafikmodi und wie man sie einschaltet.

Na, egal erstmal. Wollte nur sagen: Wenns Dir um Grafikprogrammierung unter DOS geht, kann (unter anderem) ich als Ansprechpartner dienen.
Benutzeravatar
oDOSseus
LAN Manager
Beiträge: 239
Registriert: Di 10. Aug 2010, 15:21

Re: VGA-Programmierung.

Beitrag von oDOSseus »

Hey Dosferatu,

ich danke dir erstmal für diese Ausführliche Antwort. Da ich die Schriftart-Datei ja selber lesen und schreiben muss, denke ich, ich benutze eine eigene Datei-Spezifikation. Meine Buchstaben sind alle 4x7 groß, um Platz zu sparen und bei einer Auflösung von 320x200 auch 64x25 Zeichen zu garantieren (alles andere wäre mir zu wenig). Meine Schriftart wird nur den ersten ascii-Block (bis 127 ohne Systemzeichen also 96 Zeichen) beinhalten, da ich denke, ich werde Umlaute und Block-, sowie Rahmengrafiken nicht brauchen, wenn ich sowieso schon mit Graphik arbeite.

Ich werde die Pixel auch bitweise Speichern (kann mein Bildformat .SIF ja schließlich auch). Das macht dann 2 zeichen pro byte. Das letzte byte wird dabei aber nur halb gesetzt werden. Das macht ne Dateigröße von grob 400 Bytes (muss ja noch ein kleiner Datei-Header mit rein).

Ich werde die tutorials auf deiner Seite verschlingen und Poste nochmal, wenn ichs geschafft habe oder fehlgeschlagen bin =).
DOSferatu
DOS-Übermensch
Beiträge: 1220
Registriert: Di 25. Sep 2007, 12:05
Kontaktdaten:

Re: VGA-Programmierung.

Beitrag von DOSferatu »

Ja, 4x8 Zeichen oder kleiner habe ich auch schon gemacht. Kommt halt drauf an, wie ich sie brauche. Die Zeichen für den neuen Level-Editor sind... naja, Höhe 6 Pixelzeilen, Breite eben unterschiedlich (bei Breite zähle ich immer die Leerspalte mit). Also das kleine i hat dann 2 Pixel Breite. Großbuchstaben sind eben größer usw...
Benutzeravatar
oDOSseus
LAN Manager
Beiträge: 239
Registriert: Di 10. Aug 2010, 15:21

Beitrag von oDOSseus »

Es hat geklappt die Font zu speichern.
Aber der Source-Code is so mies und zusammengewurschtelt, das kann ich hier einfach nicht posten xD
DOSferatu
DOS-Übermensch
Beiträge: 1220
Registriert: Di 25. Sep 2007, 12:05
Kontaktdaten:

Re: VGA-Programmierung.

Beitrag von DOSferatu »

Tja, was meinste, warum ich meine Sourcen nicht rausgebe? <g>
Wenn ich Codebeispiele mache, mach ich die meistens extra für die jeweilige Person / den jeweiligen Thread oder Text etc. Sourcen aus meinen Programmen kann man echt keinem anbieten.
Der Grund ist, daß ich "Programmcode schick machen" für sinnlose Zeitverschwendung halte, die man besser mit anderen Dingen nutzen könnte. Bin ja kein Skripter...
freecrac
DOS-Guru
Beiträge: 861
Registriert: Mi 21. Apr 2010, 11:44
Wohnort: Hamburg Horn

Re: VGA-Programmierung.

Beitrag von freecrac »

Hallo...
DOSferatu hat geschrieben:Die "normalen" BIOS-Zeichensätze haben eine Breite von 8 Pixeln und eine Höhe zwischen 1 und 32 Zeilen. (Wobei eigentlich in der Regel nur 8x8, 8x16 oder für diesen 43-Zeilen Mode auch 8x14 Zeichensätze benutzt werden.)
So ein "normaler" Zeichensatz ist so aufgebaut, daß jede Zeile ein Byte hat, die einzelnen Bits bestimmen, ob ein Pixel gesetzt (1) oder frei (0) ist, dabei ist das oberste Bit (also 128) der linke Pixel.
Der 9. Pixel wird nicht im Zeichensatz mitgespeichert. Ob der 9. Pixel gesetzt wird oder nicht, wird so entschieden:
Wenn das Zeichen die Nummern 192 bis 223 hat (also seine Nummer binär 110xxxxx ist), dann ist der 9. Pixel gleich dem 8. Pixel. Anderenfalls ist der 9. Pixel immer frei (also Hintergrund).

Man kann sich aber natürlich auch eigene Zeichensatz-Formate bauen. Sollten diese aber monochrom sein (nur 2 Farben, Zeichenfarbe und Hintergrundfarbe), dann ist es am besten, ebenfalls bit-basiert vorzugehen). Ich entwickle öfters mal solche "normalen" Zeichensätze (meistens 8x8) und speichere sie im selben Format wie die aus dem BIOS. Dabei hat ein Zeichensatz genau 2048 Bytes (2 kByte), nämlich 256*8. (256 Zeichen, 8 Bytes pro Zeichen). Habe aber auch schon 8*16er Zeichensätze gebaut.
Will sagen: Nein, man muß nicht 256 Files anlegen. Man kann auch alle Zeichen in einem Zeichensatz-File speichern.

Ich habe noch ein anderes Format entwickelt, das die Zeichen "senkrecht" speichert - d.h. sie haben alle die gleiche Höhe, aber können unterschiedliche Breiten haben - das dient dazu, "proportionale" Zeichen zu benutzen (also wo z.B. das i schmal ist und das W breit usw.)

Wie man das ganze darstellt, bleibt ja jedem selbst überlassen.
Die genaue Adresse der "normalen" Zeichsätze(abgelegt im Bios der Grafikkarte) für 8x8, 8x16 und 8x14 kann man wie folgt ermitteln: RBIL->inter61a.zip->INTERRUP.A

Code: Alles auswählen

--------V-101130-----------------------------
INT 10 - VIDEO - GET FONT INFORMATION (EGA, MCGA, VGA)
	AX = 1130h
	BH = pointer specifier
	    00h INT 1Fh pointer
	    01h INT 43h pointer
	    02h ROM 8x14 character font pointer
	    03h ROM 8x8 double dot font pointer
	    04h ROM 8x8 double dot font (high 128 characters)
	    05h ROM alpha alternate (9 by 14) pointer (EGA,VGA)
	    06h ROM 8x16 font (MCGA, VGA)
	    07h ROM alternate 9x16 font (VGA only) (see #00021)
	    11h (UltraVision v2+) 8x20 font (VGA) or 8x19 font (autosync EGA)
	    12h (UltraVision v2+) 8x10 font (VGA) or 8x11 font (autosync EGA)
Return: ES:BP = specified pointer
	CX    = bytes/character of on-screen font (not the requested font!)
	DL    = highest character row on screen
Note:	for UltraVision v2+, the 9xN alternate fonts follow the corresponding
	  8xN font at ES:BP+256N
BUG:	the IBM EGA and some other EGA cards return in DL the number of rows on
	  screen rather than the highest row number (which is one less).
SeeAlso: AX=1100h,AX=1103h,AX=1120h,INT 1F"SYSTEM DATA",INT 43"VIDEO DATA"

Format of alternate font table [array]:
Offset	Size	Description	(Table 00021)
 00h	BYTE	character to be replaced (00h = end of table)
 01h  N BYTEs	graphics data for character, one byte per scan line
Mit Vorliebe für höhere Videomodi kann man auch schon mal kreativer werden:

Code: Alles auswählen

;-------------------------------------- ────────────────┤
T   DB 0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0 ;       **       │
    DB 0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0 ;      ****      │
    DB 0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0 ;     ******     │
    DB 0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0 ;     ******     │
    DB 0,0,0,0,1,1,1,0,0,1,1,1,0,0,0,0 ;    ***  ***    │
    DB 0,0,0,0,1,1,1,0,0,1,1,1,0,0,0,0 ;    ***  ***    │
    DB 0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,0 ;   ***    ***   │
    DB 0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,0 ;   ***    ***   │
    DB 0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,0 ;   ***    ***   │
    DB 0,0,1,1,1,0,0,0,0,0,0,1,1,1,0,0 ;  ***      ***  │
    DB 0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0 ;  ************  │
    DB 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0 ; ************** │
    DB 0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,0 ; ***        *** │
    DB 0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,0 ; ***        *** │
    DB 1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1 ;***          ***│
    DB 1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1 ;***          ***│
;-------------------------------------- ────────────────┤
    DB 1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0 ;**************  │
    DB 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0 ;*************** │
    DB 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 ; ***************│
    DB 0,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1 ; ***        ****│
    DB 0,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1 ; ***         ***│
    DB 0,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1 ; ***         ***│
    DB 0,1,1,1,0,0,0,0,0,0,0,1,1,1,1,0 ; ***       **** │
    DB 0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0 ; *************  │
    DB 0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0 ; *************  │
    DB 0,1,1,1,0,0,0,0,0,0,0,1,1,1,1,0 ; ***       **** │
    DB 0,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1 ; ***         ***│
    DB 0,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1 ; ***         ***│
    DB 0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1 ; ***        ****│
    DB 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 ; ***************│
    DB 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0 ;*************** │
    DB 1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0 ;**************  │
;-------------------------------------- ────────────────┤
    DB 0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0 ;      *****     │
    DB 0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0 ;    *********   │
    DB 0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0 ;  ************  │
    DB 0,1,1,1,1,1,0,0,0,0,0,1,1,1,1,0 ; *****     **** │
    DB 0,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1 ; ***         ***│
    DB 1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0 ;****            │
    DB 1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0 ;***             │
    DB 1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0 ;***             │
    DB 1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0 ;***             │
    DB 1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0 ;***             │
    DB 1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0 ;****            │
    DB 0,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1 ; ***         ***│
    DB 0,1,1,1,1,1,0,0,0,0,0,1,1,1,1,0 ; *****     **** │
    DB 0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0 ;  ************  │
    DB 0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0 ;    *********   │
    DB 0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0 ;      *****     │
;-------------------------------------- ────────────────┤
Wenn Interesse, könnte ich mal eine kleine Subroutine schreiben, um Zeichen an jede Position im 320x200 Mode (Mode 13h) zu setzen, ausgehend von einem 8x8 Zeichensatz.

Ich habe hier auch (für mich selber) so Entwicklungs-Tools für Zeichensätze geschrieben. Eins für 8x8 Zeichensätze im obengenannten Format und eins für sowohl 8xIrgendwas Zeichensätze im "BIOS" Format, das aber auch proportionale Zeichensätze in meinem eigenen Format speichern kann. (Da gibt es mittlerweile zwei Formate, eins davon kann 4-farbige Zeichen generieren.)
Diese Tools sind aber... naja, voller Hotkeys und freakig zu bedienen. Wer Windows und Mausklickerei gewöhnt ist, wird sich damit etwas schwer tun...
Ich bin es gewohnt bei DOS die Mouse seltener zu benutzen und das man Hotkeys innerhalb von Anwendungen verwendet ist auch in Windows noch weit verbreitet. Ein DOS-Benutzer sollte auch ganz gut ohne aufpoppende Fenster seinen PC bedienen können.
Ich hab auf meine Webseite auch einige Tutorials geschrieben, aber der Text "Wie funktioniert Grafik?" setzt an einigen Stellen geringfügige Assembler-Kenntnisse voraus.
Beim Programmieren in Assembler wird auf die Funktionsweise der CPU eingegangen in dem man verschiede CPU-Register benutzt, um damit beliebige Werte und Adressen zu verarbeiten und den verfügbaren Speicher für die jeweiliegen Aktionen zu verwenden. Eine Anzahl einfacher Befehle(mit ihren entsprechenden Opcodes) stehen dafür zur Verfügung. Die Befehle selber werden als Mnemonics geschrieben so das man die Opcodes nicht Bytesweise von Hand codieren muss. Der verwendete Assemler/Compiler wandelt den Assembler-Sourcode in ein Binary-Format.
Aber da beschreibe ich auch den Aufbau der verschiedenen Grafikmodi und wie man sie einschaltet.

Na, egal erstmal. Wollte nur sagen: Wenns Dir um Grafikprogrammierung unter DOS geht, kann (unter anderem) ich als Ansprechpartner dienen.
Ich helfe auch gerne.

Dirk
Benutzeravatar
oDOSseus
LAN Manager
Beiträge: 239
Registriert: Di 10. Aug 2010, 15:21

Re: VGA-Programmierung.

Beitrag von oDOSseus »

Die font ist jetzt vollständig implementiert (Lese/schreibe/Anezeige-Möglichkeit)
Ich kenne mich zwar in ASM aus und mag die sprache, jedoch halte ich ASM so gut es geht aus dem C-Code heraus, damit da kein compiler schwierigkeiten bekommt.
DOSferatu
DOS-Übermensch
Beiträge: 1220
Registriert: Di 25. Sep 2007, 12:05
Kontaktdaten:

Re: VGA-Programmierung.

Beitrag von DOSferatu »

freecrac hat geschrieben:Hallo...
[...]
Beim Programmieren in Assembler wird auf die Funktionsweise der CPU eingegangen in dem man verschiede CPU-Register benutzt, um damit beliebige Werte und Adressen zu verarbeiten und den verfügbaren Speicher für die jeweiliegen Aktionen zu verwenden. Eine Anzahl einfacher Befehle(mit ihren entsprechenden Opcodes) stehen dafür zur Verfügung. Die Befehle selber werden als Mnemonics geschrieben so das man die Opcodes nicht Bytesweise von Hand codieren muss. Der verwendete Assemler/Compiler wandelt den Assembler-Sourcode in ein Binary-Format.
Ja, das ist mir bewußt. Schließlich hab ich ja den Text selber geschrieben. Ich meinte nur, daß ich in diesem Text die verschiedenen Arten, wie man die Grafikmodi setzt und benutzt, mit Beispielen beschrieben habe und diese hab ich halt mit einigen Assembler-Befehlen gemacht. Aber es sind ja keine besonders "schwierigen" Befehle, nur ein paar MOVs, INTs, und IN/OUTs.
DOSferatu
DOS-Übermensch
Beiträge: 1220
Registriert: Di 25. Sep 2007, 12:05
Kontaktdaten:

Re: VGA-Programmierung.

Beitrag von DOSferatu »

oDOSseus hat geschrieben:Ich kenne mich zwar in ASM aus und mag die sprache, jedoch halte ich ASM so gut es geht aus dem C-Code heraus, damit da kein compiler schwierigkeiten bekommt.
[persönliche Meinung]
Bei mir ist es genau umgekehrt: Ich bin über jedes Byte Assembler (bzw jedes Mnemonic), das ich in meine Sourcen einfügen kann, froh - gerade wenn ich Dinge schnell und systemnah bekommen will.
Ich verlasse mich total ungern alleine auf den Compiler. Und ja, ich weiß, daß einige (oft vor allem C-Coder, obwohl ich das nicht persönlich meine) Leute der Ansicht sind, daß ihre Compiler besser optimieren als Menschen, die in ASM coden und teilweise auf Byte-Ebene und mit selbstmodifizierendem Code arbeiten und Register teilweise über mehrere kByte Code hinweg immer noch benutzen (weil sie wissen, was drinsteht), etc... Aber da gehen die Meinungen sowieso auseinander.
Ich selber benutze meinen einen Compiler und an "systemübergreifenden" Programmen habe ich kein Interesse - mein System ist ein x86-Rechner und andere Systeme haben sowieso nicht die gleiche Hardware. Und je "hardwareferner" ich coden würde, umso langsamer würde das werden - daher mag ich keine "generalisierten" Compiler. Ich weiß zwar, daß man die dann mit etlichen Compilerschaltern dazu kriegen kann, sich an die jeweilgen Systeme (leidlich) anzupassen - aber oft sind die Sourcen dann hinterher so, daß man weniger Arbeit hätte, wenn man gleich für jedes System, auf dem man sie portieren will, einen eigenen Code geschrieben hätte.
[/persönliche Meinung]
freecrac
DOS-Guru
Beiträge: 861
Registriert: Mi 21. Apr 2010, 11:44
Wohnort: Hamburg Horn

Re: VGA-Programmierung.

Beitrag von freecrac »

oDOSseus hat geschrieben:Die font ist jetzt vollständig implementiert (Lese/schreibe/Anezeige-Möglichkeit)
Ich kenne mich zwar in ASM aus und mag die sprache, jedoch halte ich ASM so gut es geht aus dem C-Code heraus, damit da kein compiler schwierigkeiten bekommt.
Ich kenne mich mit C/C++ überhaupt nicht aus. Welche Probleme könnten denn beim Compilieren eines C-Codes auftreten wenn man dort ASM integriert?

Dirk
freecrac
DOS-Guru
Beiträge: 861
Registriert: Mi 21. Apr 2010, 11:44
Wohnort: Hamburg Horn

Re: VGA-Programmierung.

Beitrag von freecrac »

DOSferatu hat geschrieben:
freecrac hat geschrieben:Hallo...
[...]
Beim Programmieren in Assembler wird auf die Funktionsweise der CPU eingegangen in dem man verschiede CPU-Register benutzt, um damit beliebige Werte und Adressen zu verarbeiten und den verfügbaren Speicher für die jeweiliegen Aktionen zu verwenden. Eine Anzahl einfacher Befehle(mit ihren entsprechenden Opcodes) stehen dafür zur Verfügung. Die Befehle selber werden als Mnemonics geschrieben so das man die Opcodes nicht Bytesweise von Hand codieren muss. Der verwendete Assemler/Compiler wandelt den Assembler-Sourcode in ein Binary-Format.
Ja, das ist mir bewußt. Schließlich hab ich ja den Text selber geschrieben. Ich meinte nur, daß ich in diesem Text die verschiedenen Arten, wie man die Grafikmodi setzt und benutzt, mit Beispielen beschrieben habe und diese hab ich halt mit einigen Assembler-Befehlen gemacht. Aber es sind ja keine besonders "schwierigen" Befehle, nur ein paar MOVs, INTs, und IN/OUTs.
Ich glaube ich bin hierbei etwas betriebsblind und kann mir nicht so recht vorstellen wann es schwieriger wird. Welche ASM-Befehle, oder welche Menge an Assembler-Code wären denn als schwieriger zu bezeichnen?

Dirk
freecrac
DOS-Guru
Beiträge: 861
Registriert: Mi 21. Apr 2010, 11:44
Wohnort: Hamburg Horn

Re: VGA-Programmierung.

Beitrag von freecrac »

DOSferatu hat geschrieben:
oDOSseus hat geschrieben:Ich kenne mich zwar in ASM aus und mag die sprache, jedoch halte ich ASM so gut es geht aus dem C-Code heraus, damit da kein compiler schwierigkeiten bekommt.
[persönliche Meinung]
Bei mir ist es genau umgekehrt: Ich bin über jedes Byte Assembler (bzw jedes Mnemonic), das ich in meine Sourcen einfügen kann, froh - gerade wenn ich Dinge schnell und systemnah bekommen will.
Ich verlasse mich total ungern alleine auf den Compiler. Und ja, ich weiß, daß einige (oft vor allem C-Coder, obwohl ich das nicht persönlich meine) Leute der Ansicht sind, daß ihre Compiler besser optimieren als Menschen, die in ASM coden und teilweise auf Byte-Ebene und mit selbstmodifizierendem Code arbeiten und Register teilweise über mehrere kByte Code hinweg immer noch benutzen (weil sie wissen, was drinsteht), etc... Aber da gehen die Meinungen sowieso auseinander.
Ich selber benutze meinen einen Compiler und an "systemübergreifenden" Programmen habe ich kein Interesse - mein System ist ein x86-Rechner und andere Systeme haben sowieso nicht die gleiche Hardware. Und je "hardwareferner" ich coden würde, umso langsamer würde das werden - daher mag ich keine "generalisierten" Compiler. Ich weiß zwar, daß man die dann mit etlichen Compilerschaltern dazu kriegen kann, sich an die jeweilgen Systeme (leidlich) anzupassen - aber oft sind die Sourcen dann hinterher so, daß man weniger Arbeit hätte, wenn man gleich für jedes System, auf dem man sie portieren will, einen eigenen Code geschrieben hätte.
[/persönliche Meinung]
Ich habe mir bei kleinen überschaubaren C-Listings nach dem Compilieren mal angeschaut wie der Compiler den Code umsetzte und ich hatte den Eindruck das man es selber kaum besser machen kann. Doch wenn ich mir andere C-Listings so anschaue frage ich mich oft was das überhaupt soll, wenn dort manche Zeiger auf Zeiger auf Zeiger verweisen, so das man nicht sofort erkennen kann welche Adresse nun letzendlich die eigentlich Speicheradresse ist worauf zugegriffen werden soll. So bläht sich der gesamte C-Code nur unnötig auf und macht es so schwerer den Überblick zu behalten. Vergleichsweise könnte man auch mit Assembler für jeden Mov-Befehl eine eigene Subroutine mit nur einem dort enthaltenen Befehl schreiben und dafür hin und her springen um diesen einen Befehl ein einziges Mal auszuführen. Doch ich bin immer bemüht meinen Code so klein und überschaubar wie möglich zu halten, so das man sofort erkennen kann auf welche Speicherbereiche zugegriffen wird und wie die Aufgabe im Ganzen umgesetzt wird. Dabei verwende ich bei sehr kleinen Anwendungen auch schon mal Soft-Interrupts um beispielweise eine Textausgabe zu machen. Doch in der Regel verzichte ich darauf und schreibe lieber direkt in den Textram, auch wenn dadurch der Source-Code etwas länger wird. Doch in der Ausführung werden dann nicht mehr die vielen für unsere Aufgabe nicht benötigten Befehle ausgeführt die beim Soft-Interrupt immer abgearbeitet werden und die eigentlich nur die Ausführung verzögern, ganz ohne das es überhaupt irgendeinen Nutzen für unsere Anwendung hat.

Wenn ich mir also solche C-Listings mit Zeiger verweisen auf Zeiger anschaue verwundert es mich nicht wirklich das man dabei den Überblick verliert und dann solche Dinge passieren wie etwa das ein Pufferüberlauf dazu führen kann das dort ein Sicherheitsloch entsteht. Bei Assembler behält man einfach automatisch mehr den Überblick auf solche Daten-Felder, so das wenn überhaupt man sich nur um ein Byte/Word/Dword nehr oder weniger verrechnen kann und es somit quasi völlig ausgeschlossen ist, das es so ein Pufferüberlauf überhaupt auftreten kann der ein solches Sicherheitsloch verursachen könnte.

Dirk
Benutzeravatar
oDOSseus
LAN Manager
Beiträge: 239
Registriert: Di 10. Aug 2010, 15:21

Re: VGA-Programmierung.

Beitrag von oDOSseus »

@Freecrac

Also:
Es gibt 16bit und 32bit compiler. Es gibt compiler für DOS/windows/Linux/Mac. Das heißt, wenn ich auf einem 32bit-compiler für ein 32bit DOS code, wird der code GARANTIERT nicht unter 16bit DOS laufen. Ich müsste dazu alle zugriffe auf die Register ändern und andere lösungen finden. Programmiere ich allerdings in C (nicht c++, denn c++ erstellt mir meiner meinung nach zu große EXEn) dann werden dort keine Probleme auftreten.
Und wenn ich ASM in C einbinde (also inline), dann kann es sein, dass unterschiedliche compiler eine andere Syntax haben. Es gibt ja auch eine fülle von Assemblern deren syntax immer verschieden ist.
Dies sind alles gründe nur wenig ASM in C einzubauen, falls man den Sourcecode teilen will, um Menschen damit zu helfen oder falls man das Programm nicht nur auf seinem eigenen PC ausführen will.

Zum Thema Zeiger auf Zeiger:
Zeiger auf zeiger sind sowas ähnliches wie ein zweidimensionales Array. Das ist mehr als elegant um String-Arrays zu spreichen. Da durcheinanderzukommen ist meiner meinung nach sehr schwer. Also ich bin da noch nie durcheinandergekommen, da ich meinen source-code dokumentiere und das klappt eig immer. Sich nicht mehr mit adressen rumzuschlagen ist doch grade das, was Hochsprachen erreichen wollen. so auch der ASM-code (Mnemonic).
freecrac
DOS-Guru
Beiträge: 861
Registriert: Mi 21. Apr 2010, 11:44
Wohnort: Hamburg Horn

Re: VGA-Programmierung.

Beitrag von freecrac »

oDOSseus hat geschrieben:@Freecrac

Also:
Es gibt 16bit und 32bit compiler. Es gibt compiler für DOS/windows/Linux/Mac. Das heißt, wenn ich auf einem 32bit-compiler für ein 32bit DOS code, wird der code GARANTIERT nicht unter 16bit DOS laufen.
Natürlich nicht, da Registersize-, Adresssize- und Operandsize -Prefixe mit oder ohne nun eine umgekehrte Bedeutung haben.
Ich müsste dazu alle zugriffe auf die Register ändern und andere lösungen finden.
Beispiel: Wenn man 32 Bit-Register im 32bit-Mode benutzten möchte, dann darf dort kein Registersize-Prefix vor dem Opcode plaziert sein. Das selbe gilt für 32Bit-Adressen und 32Bit-Operanden.
Werden diese Prefixe im 32bit-Mode vor dem Opcode plaziert, dann verwendet die CPU nur 16 Bit-Register/Operanden und Adressen.

Und umgekehrt im 16Bit-Mode müssen dafür die entsprechenden Prefixe vor dem Opcode plaziert sein wenn man 32Bit-Register, 32Bit-Operanden und 32Bit-Adressen benutzen möchte.
Das ist das einzige Unterscheidungsmerkmal für den 16Bit und den 32Bit-Mode. Beide Modi lassen sich prinzipiell im PM sowei auch im RM benutzen.
Nur kann man im 32Bit-RM dann kein DOS oder BIOS oder Interrups mehr benutzen/zulassen, weil die dortigen Routinen für den 16Bit-RM entwickelt wurden.
Programmiere ich allerdings in C (nicht c++, denn c++ erstellt mir meiner meinung nach zu große EXEn) dann werden dort keine Probleme auftreten.
Und wenn ich ASM in C einbinde (also inline), dann kann es sein, dass unterschiedliche compiler eine andere Syntax haben. Es gibt ja auch eine fülle von Assemblern deren syntax immer verschieden ist.
Für x86er sind eigentlich nur zwei verschiedene Syntax verbreitet. Programmierer die GAS verwenden benutzen meist den AT&T Syntax, der in der Unix-Welt ein Standard ist.
Aber auch mit GAS ist es möglich den Intel Syntax zu verwenden wie auch andere Assembler wie z.B. TASM, MASM und NASM.
Dies sind alles gründe nur wenig ASM in C einzubauen, falls man den Sourcecode teilen will, um Menschen damit zu helfen oder falls man das Programm nicht nur auf seinem eigenen PC ausführen will.
Man kann ja im Kopf des Source-Codes angeben womit compiliert werden kann.
Zum Thema Zeiger auf Zeiger:Zeiger auf zeiger sind sowas ähnliches wie ein zweidimensionales Array.
Ich betrachte es eher als Umleitung in eine Umleitung, so das man nicht auf direktem Weg ans Ziel kommt.
Das ist mehr als elegant um String-Arrays zu spreichen.
Auch ich habe schon eine Sprungtabelle verwendet, so das in einer paralell dazu sich befindenden Tabelle mit Ergebnissen die Auswahl getroffen wird und die Sprungtabelle dazu verwendet wird auf verschiedene Ergebnisse und Tabelleneinträge an verschieden Adressen zu springen.
Doch das ist doch etwas ganz anderes. Denn bei so etwas kann ich den Sinn erkennen.

Doch was soll es bringen wenn ein Zeiger z.B. mit dem Namen A-Zeiger zu einer Adresse zeigt wo der B-Zeiger enthalten ist und der dann erst auf die Adresse zeigt mit dem gewünschten String den wir erreichen wollen.
Eigentlich bräuchte man nur den letzten Zeiger der wirklich auf unseren String zeigt und der A-Zeiger ist einfach nur völlig überflüssig. Genau so etwas macht den C-Code für mich so unleserlich.
Wenn ich mir die Linux-Sourcen so anschaue bekomme ich immer wieder das kalte Grauen und ich frage mich welcher Wahnsinnige das nur verbockt hat.
Da durcheinanderzukommen ist meiner meinung nach sehr schwer. Also ich bin da noch nie durcheinandergekommen, da ich meinen source-code dokumentiere und das klappt eig immer. Sich nicht mehr mit adressen rumzuschlagen ist doch grade das, was Hochsprachen erreichen wollen.
Mit Pascal habe ich nicht diese Probleme.
so auch der ASM-code (Mnemonic).
Zeiger mit Namen auf den Datenbereich sind ja auch sinnvoll und so kann man ohne sich um die genaue Adresse zu kümmern dazwischen immer wieder Daten einfügen ohne das vorherigen Einträge falsch adressiert werden.

Aber auch dort könnte ich ein String beispielweise nach DS:1000 platzieren und dann einen Zeiger darauf in DS:0 ablegen. Doch ganz bestimmt bin ich nicht so verrückt zu erst einen Zeiger von DS:0 nach DS:4 und von dort nach DS:8 zu legen wo dann letztendlich erst der eigentliche Zeiger auf DS:1000 hinzeigt. Das ist in meinen Augen völliger Schwachsinn ganz ohne jeden Wert und das macht den Code allenfalls völlig unleserlich. Und genau mit solchen Zeiger auf Zeiger auf Zeiger ärgere ich mich ständig herum wenn ich mir verschiedene C-Listings anschaue.
Für mich der reinste Wahnsinn.

Zum Abschluss noch ein kleiner Hinweis. Ich bevorzuge Vesamodi die ich mit meiner GraKa bis zu 1920x1200x32 anschalten kann. Bei Interesse siehe auch dazu meine Beiträge hier:
http://www.dosforum.de/viewtopic.php?f=15&t=2921

Dirk
Antworten