Register for your free account! | Forgot your password?

Go Back   elitepvpers > Coders Den > General Coding > Coding Tutorials
You last visited: Today at 03:48

  • Please register to post and access all features, it's quick, easy and FREE!

Advertisement



Eigene Software CPU + Instruction Set entwerfen [HowTo]

Discussion on Eigene Software CPU + Instruction Set entwerfen [HowTo] within the Coding Tutorials forum part of the General Coding category.

Reply
 
Old   #1
 
Crossside's Avatar
 
elite*gold: 0
Join Date: Dec 2013
Posts: 2,095
Received Thanks: 506
Eigene Software CPU + Instruction Set entwerfen [HowTo]

Hey,
Vielleicht haben sich schon manche hier gefragt wie sie sich einen eigenen Emulator programmieren können. Oft bekommt man bei solch einer Frage Antworten wie "Lern Programmieren" "Kauf dir Bücher, Lern einige Jahre Programmieren und dann weißt du es schon". Das ist nicht sonderlich hilfreich weil es nicht spezifisch auf die Hauptfrage eingeht wie sowas funktioniert.

Es gibt zwar Tutorials die zeigen wie man z.b einen Gameboy Emulator bastelt, aber ich fande das nie wirklich Informativ genug.. das wäre dann vielmehr ein Copy Paste gewesen hätte ich mir damit einen Emulator zusammengebaut. Deshalb entschloss ich damals es sein zu lassen.
Gestern kam mir aber dann die Idee weil ich mich grade mit Assembler befasse. Mir kam der Gedanke "Ich hätte gern eine Art eigenen Interpreter für eine eigene Assemblerähnliche Sprache..!". Meine Idee war es, eine Art Interpreter zu basteln mit eigenem Befehlssatz der Assembler angelehnt war.. jedoch so das ich das ganze konkret auf meine Bedürfnisse anpassen konnte.
Als ich kurz davor war fertig zu werden mit der Planung merkte ich.. "Hey.. das ist doch ne Software CPU was ich hier grade Plane.. Das ist doch wie Emulatoren aufgebaut sind..!". Ich habe also ne CPU im Softwareformat geplant ohne es zu merken zunächst.

Was sind nun aber die Vorteile von einer eigenen (Softwarebasierten) "CPU"?

- Die dafür geschriebenen Programme sind sehr klein (Dateigröße)
- Es ist sehr portabel (man benötigt nur die cpu als Binary)
- Man lernt etwas mehr wie Computer und Emulatoren funktionieren

Die Idee stand nun also..
Nun musste ich entscheiden "Was benötige ich?"..
Ich entschied mich für folgende Eigenschaften:

Code:
Daten-Register: 
- C0
- C1
- C2
- C3
- C4
- C5

System-Register:
- IP (Instruction Pointer)
- EC (Error Code - benutzt um Errorcodes zurückzuliefern)  
- RC (Run Cycles - Anzahl bisher ausgeführte Befehle)
- Memory (Programmcode der ausgeführt werden soll)
Nichts komplexes, sondern das notwendigste halt..
Doch nur mit Registern allein kann man nichts anfangen.. es fehlen noch die Befehle! Ich habe also überlegt was ich benötigen werde an funktionen..
Ich habe diese Befehle so Basic gehalten wie nur möglich - keine String Manipulationen, Kein Netzwerk Kram oder sonstwas.. sondern Grundlegende Basic Dinge auf denen man weitere Funktionen aufbauen kann.

Beispiel:

Ich habe keine For oder While Schleife implentiert als Befehlssatz, sondern Funktionen die Multifunktionell sind und mit denen man dann auch For, While etc. realisieren kann - und mehr.

Am Ende kam folgender Befehlssatz herraus (Die Zahlen sind die Opcodes):

Code:
Arithmetik:
ADD     = 00
DEC     = 01
MUL     = 02
DIV     = 03

Register Funktionen:
CNST    = 04
POP     = 05
INSNUM  = 06
INSSTR  = 07
CHECK   = 08

Sprünge:
JMPLE   = 09
JMPEQ   = 10
JMPGE   = 11

Interactive:
PRINT   = 12
INPUT   = 13

Other:
NOP     = 14
EXIT    = 15

Register:
C0     = 00
C1     = 01
C2     = 02
C3     = 03
C4     = 04
C5     = 05
IP      = 06
EC     = 07
RC     = 08
MEMORY = 09
Mit diesen Grundfunktionen kann man nun die Register Manipulieren, Grundrechenarten ausführen, Inhalte von Registern befüllen, Text ein & ausgeben, Register clearen und einiges weiteres.

Nun haben wir also unsere Register um unsere Daten zu speichern die wir in unseren Programmen benötigen, und auch die Funktionen die wir benötigen um unsere Programme aufzubauen.

Wie funktioniert nun unsere CPU?
Ich erkläre euch mal den Grundlegenden Ablauf wie das ganze vom Ablauf ist..


1)
Wir tragen unser Programm das in Form von Opcodes vorliegt in unser MEMORY Register. Das Memory Register enthält unseren gesamten Programmcode.

Unser Opcode sieht Beispielsweise so aus:
Code:
06 00 00 //INSNUM 0 0
06 01 01 //INSNUM 1 1
06 02 09 //INSNUM 2 9
06 04 12 //INSNUM 4 12
00 00 01 //ADD 0 1
08 03 00 02 //CHECK 3 0 2
09 03 04 //JMPLE 3 4
15 //EXIT
Damit unsere CPU diesen Opcode nun noch verarbeiten kann, entfernen wir zum einen die zusätzlichen 0´en (erzeugt sonst ein Javascript Problem) und die Kommentare..

Unser Opcode sieht nun folgendermaßen aus:

Code:
new Array(6,0,0,6,1,1,6,02,9,6,4,12,0,0,1,8,3,0,2,9,3,4,15);
2)

Nun sagen wir unserer CPU "Hey, ich habe hier ein Programm..lauf das Programm mal durch und führe es aus".
Doch wie macht unsere CPU dies? Nun.. unsere CPU hat die gesamten Funktionen die wir als Befehlsatz haben bereits vorhanden, und da diese Befehle jeweils bestimmten Opcodes zugeordnet sind weiß es welche Befehle ausgeführt werden sollen.

In unserem Beispiel steht als Beispiel am Anfang

Code:
6 0 0
Der Opcode 06 steht für den Befehl INSNUM.
Und da wir wissen das unser Befehl INSNUM 2 Werte annimmt, weiß unsere CPU auch das diese Werte jeweils auf IP+1 und IP+2 liegen (Instruction Pointer).

Der Instruction Pointer könnt ihr euch Vorstellen wie eine Positionsangabe für die Position an der wir uns zur Zeit in unserem Programm befinden.
Befinden wir uns beim Start des Programms, steht der IP auf 0.
Führen wir nun aber unser erstes INSNUM aus, wird der IP um 3 erhöht.
Wieso? Nunja, der Opcode für INSNUM ist 06.. das ist die erste Stelle.
Die 2 Werte die INSNUM benötigt stehen jeweils an IP+1 (0) und IP+2 (0).
Diese 2 Werte nehmen weitere 2 Stellen in unserem Programm ein.

2+1 = 3.. Deshalb 3 Stellen.

Wir wissen nun also das wir beim nächsten Sprung nicht nur den Instruction Pointer um eins erhöhen dürfen, weil wir sonst ein Crash in unserem Programm erzeugen würden. Wir müssen zum nächsten Befehl springen, und dieser liegt 3 Schritte vorne. Das erhöhen des Instruction Pointer müssen wir aber nicht manuell in unserem späteren Programm das in Opcode vorliegt erledigen - das macht die CPU für uns sobald sie den Befehl ausgeführt hat.

Wenn wir nun unseren ersten Befehl abgearbeitet haben, springen wir anschließend zum nächsten Befehl.. dieser wird dann auch wieder ausgeführt. Das macht unsere CPU mit allen Befehlen bis sie am Ende des Programmes angekommen ist (Opcode 15, Exit).

Das ist Grundsätzlich was hierbei passiert.
Die einzelnen Funktionen die wir im Befehlssatz stehen haben erfüllen verschiedene Funktionen. Wir können mit ihnen an andere Stellen im Programm springen, Daten speichern, Rechnungen ausführen, Text einlesen und ausgeben und weitere Dinge.

Lassen wir uns doch mal anschauen wie das ganze nun implentiert ausschaut, okay? Damit ihr auch ein Verständniss davon habt wie das ganze dann in Code ausschauen kann

Unser Befehlssatz:

Programm Befehle parsen & ausführen (Opcode):

Wir haben hier noch zusätzlich einige Dinge im Code wie Beispielsweise die Errorcodes.. das ist deshalb vorhanden damit das Debuggen des Programmcodes erleichtert wird. Es ist enorm Dämlich wenn man nicht weiß wo der Fehler steckt.. deshalb gibt es Errorcodes die bei bekannten Fehlern dann jeweils das Error-Code Register befüllen.

Mit dem bisher vorhandenen können wir nun schon unser erstes Programm schreiben das unsere CPU ausführen kann

Was kann das Programm? Es ist eine For-Schleife die von 0 bis 9 zählt

Zunächst bauen wir das Programm für Menschen lesbar auf damit wir es einfach haben.. wir benutzen hierfür keine Opcodes sondern die normalen Befehle die wir zur Verfügung haben.

Code:
INSNUM C0, 0 //var a = 0
INSNUM C1, 1 //var b = 1
INSNUM C2, 9 //for(x<9)
INSNUM C4, 12 //Speicherstelle 12 vormerken
ADD C0, C1 //C0 = C0 + C1
CHECK C3, C0, C2 //Vergleiche C0 mit C2 um festzustellen ob schon 9-10 Durchläufe durchgelaufen sind. Ergebniss in C3 packen
JMPLE C3, C4 //C3 kleiner? Springe zu Speicherstelle die in C4 vorgemerkt ist
EXIT //Schleife fertig? Programm beenden
Das ganze ist gleichzusetzen mit folgendem Code:

Code:
for(int x=0;x<9;x++)
{

}
Das ganze ist nur etwas umständlicher gestaltet da wir hier mit Basic-Befehlsatz arbeiten und wir deshalb uns was einfallen lassen haben müssen

Kurz gesagt definieren wir 2 Werte.. einmal die Zahl 0 und einmal die Zahl 1.
Wir zählen diese Werte nun immer wieder zusammen ..

0+1
1+1
2+1
3+1
...
Dadurch zählt unser Programm immer um eins höher.
Und unser Programm kontrolliert nach jedem Durchlauf "haben wir schon die 9 erreicht?". Wenn die 9 erreicht ist, beendet sich unser Programm.

Da unsere CPU aber mit dem oben geschriebenen Programm so nichts anfangen kann, müssen wir das ganze in Opcode umwandeln.
Opcode steht für Operationscode.. kurzgesagt ist dies einfach eine Zahl die einem Befehl zugeordnet ist (siehe oben der Befehlssatz inklusive der Opcodes). Fangen wir also mal an..

Code:
06 00 00 //INSNUM 0 0
06 01 01 //INSNUM 1 1
06 02 09 //INSNUM 2 9
06 04 12 //INSNUM 4 12
00 00 01 //ADD 0 1
08 03 00 02 //CHECK 3 0 2
09 03 04 //JMPLE 3 4
15 //EXIT
Zur Verständniss habe ich noch die Kommentare drin gelassen, die kommen später aber weg. Ebenfalls die zusätzlichen 0´en - das liegt aber nicht an der CPU sondern daran weil Javascript eine zusätzliche 0 (z.b 07,08,09 usw) als Octale Zahl sieht und dann meckert. Konvertieren wir unser Programm nun dahingehend das unsere CPU was damit anfangen kann.. sieht das so aus..

Code:
Schritt 1)
06 00 00 06 01 01 06 02 09 06 04 12 00 00 01 08 03 00 02 09 03 04 15

Schritt 2)
new Array(6,0,0,6,1,1,6,02,9,6,4,12,0,0,1,8,3,0,2,9,3,4,15);
Dieses Array (unser Programmcode) fügen wir nun testweise in unsere CPU in das MEMORY Register ein, und dann testen wir das ganze auch schon..

Und.. es klappt! Wuhu *freu*
Unser Programm wird abgearbeitet, und zählt bis 9

Wir haben nun also eine eigene kleine Software CPU womit wir Mini Programme schreiben können die enorm klein von der Dateigröße her sind und freuen uns einen Ast

Für alle die der Gesamte Code, die Dokumentation etc. Interessiert habe ich hier mal einen Download-Link für die Javascript Dateien inklusive Dokumentationen des Befehlssatzes.



Virustotal:


Es wäre möglich das sich noch der ein oder andere Bug darin befindet.. solltet ihr einen finden könnt ihr mir gerne ne PM schicken. Ich werde den Befehlssatz sicher auch in Zukunft vielleicht noch erweitern.
Zudem noch als Erwähnung.. der Quellcode ist nicht auf Schnelligkeit ausgelegt oder sonstwie Optimiert. Das ganze diente mir nur als Lern-Hilfe um dahinter zu steigen wie sowas funktioniert & ist bisher meine erste CPU Emulation. Seit also bitte nicht zu Streng wegen dem Code

grüße
Crossside is offline  
Thanks
9 Users
Old 12/15/2014, 22:31   #2
 
alpines's Avatar
 
elite*gold: 60
Join Date: Aug 2009
Posts: 2,256
Received Thanks: 815
Schaut interessant aus, werde ich mir mal durchlesen und Feedback geben.

Auf jeden Fall schon mal nicht schlecht, ich würde noch eine Einleitung sowie Gliederung mit Inhaltsverzeichnis hinzufügen.
alpines is offline  
Thanks
1 User
Old 12/16/2014, 09:45   #3
 
NotEnoughForYou's Avatar
 
elite*gold: 0
Join Date: Jun 2010
Posts: 3,406
Received Thanks: 2,024
Wenn man sich mit den Grundlagen der RT Ebene beschäftigen will kann man auch sehr gut mit einem Toy Prozessor Emulator oder ähnlichem üben, ähnelt sehr stark deinem Befehls Satz, auch wenn der toy Prozessor nur 4 bit op hat. Für den Anfang zum Verständnis ist das sehr gut geeignet.
NotEnoughForYou is offline  
Old 12/16/2014, 12:52   #4


 
elite*gold: 1091
Join Date: Jun 2007
Posts: 19,836
Received Thanks: 7,180
Nett, danke.

Wobei ich nun aber nicht genau den Nutzen dahinter verstehe. Du implementierst das in JavaScript und schreibst deinen eigenen Befehlssatz - wozu sollte man das genau tun? JavaScript bietet doch bereits die Basis, oder nicht? Wie würde das jetzt aussehen wenn ich beispielsweise einen Gameboy hier stehen habe den ich auf meiner Windows Kiste emuliert haben möchte? Was muss dann erledigt werden (ganz abstrakt)?

Da fehlt etwas der Zusammenhang, kann auch sein dass ich es einfach nicht kapiere weil ich nur die Basics in Assembler kann.
Mostey is offline  
Old 12/16/2014, 15:26   #5
 
Crossside's Avatar
 
elite*gold: 0
Join Date: Dec 2013
Posts: 2,095
Received Thanks: 506
Quote:
Originally Posted by Mostey View Post
Nett, danke.

Wobei ich nun aber nicht genau den Nutzen dahinter verstehe. Du implementierst das in JavaScript und schreibst deinen eigenen Befehlssatz - wozu sollte man das genau tun? JavaScript bietet doch bereits die Basis, oder nicht? Wie würde das jetzt aussehen wenn ich beispielsweise einen Gameboy hier stehen habe den ich auf meiner Windows Kiste emuliert haben möchte? Was muss dann erledigt werden (ganz abstrakt)?

Da fehlt etwas der Zusammenhang, kann auch sein dass ich es einfach nicht kapiere weil ich nur die Basics in Assembler kann.
Grundsätzlich muss man genau das tun was ich oben beschrieben habe.
Nur mit dem Unterschied das man halt keine eigenen erfundenen Register und Befehle implentiert, sondern die der Gameboy CPU (Befehlssatz ist an den Z80 angelehnt).

Gameboy Roms sind auch nur Programme die interpretiert werden, so wie ich es hier grob gezeigt habe - nur das noch Dinge wie Grafiken, Töne etc. hinzukommen. Möchte man nun einen Gameboy Emulator basteln, muss man noch zusätzlich zur CPU die anderen Elemente des Gameboy dazu implentieren (Managen von Grafiken wie Sprites, Hintergründe, Tongenerator, Steuerung der Programme mit Buttons, Takt-Frequenzen damit die Spiele nicht ultra schnell oder ultra langsam abspielen usw).

Grundsätzlich kann man sagen das die CPU des Gameboys ein Z80 ist mit veränderten Opcodes & Registern. Einige Befehle kamen hinzu, andere wurden entfernt. Trotzallem ist es sehr ähnlich wie der Z80 ( Zilog Z80 ? Wikipedia ).

Sollte dich das Thema weiterhin interessieren kannst du dir unteranderem anschauen, dort wird etwas näher darauf eingegangen. Zusätzlich gibt es noch haufenweise Informationsmaterial wenn man nach "gameboy cpu" oder "gameboy register" sucht

Falls du mal eine Übersicht über den Befehlssatz des Gameboys haben möchtest..
Ganz unten stehen auch die Register des Gameboys.



Ist also ziemlich Schreibarbeit den zu implentieren & zu testen im vergleich zu meinem kleinem ..

Hier sieht man auch wie man von Anfang bis Ende in Javascript einen Gameboy Emulator implentiert (ist ziemlich viel Arbeit) ->



+



grüße
Crossside is offline  
Thanks
1 User
Reply

Tags
cpu, emulation, emulator, javascript


Similar Threads Similar Threads
[Minecraft Accounts] Eigene Namenswahl & E-Mail inklusive | Preiswert ~ Massenrabatte
07/01/2013 - Minecraft Trading - 11 Replies
http://www.imgbox.de/users/public/images/DMeggh4z8 N.jpg Leider hat ein alter Freund, dem ich mein Passwort anvertraut hatte meinen alten EPvP Account, E-Mail sowie Skype Account entwendet, wodurch ich gezwung war diesen Thread neu zu eröffnen. Falls daran zweifel bestehen dürft Ihr die Admins gerne bitten die IP's der User zu vergleichen, die auf den beiden Accounts waren. ___________________________________
[Minecraft Accounts] Eigene Namenswahl & E-Mail inklusive | Preiswert ~ Massenrabatte
06/30/2013 - Minecraft Trading - 51 Replies
http://www.imgbox.de/users/public/images/xJSsScG8l v.jpg Guten Tag liebe Minecraft-Trading Sektion, hier werde ich euch in Zukunft Minecraft Accounts anbieten. Die von mir angebotenen Accounts beinhalten die E-Mail auf die, diese Registriert sind. Außerdem ist es möglich deine eigene Namenswahl zu treffen und somit deinen ganz privaten Minecraft Account zu personalisieren.
[Frage] wie kann ich eigene Sets/masken entwerfen
10/17/2011 - Flyff Private Server - 8 Replies
^this^ ich würde gerne für einen flyff pserver eine hater maske machen aber ich habe keine ahung gibt es da vids etdc also welche progs brauche ich etc ^^
[Howto] Compile Trinitycore - Inklusive Core Updates
09/23/2010 - WoW Private Server - 14 Replies
...



All times are GMT +1. The time now is 03:48.


Powered by vBulletin®
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Support | Contact Us | FAQ | Advertising | Privacy Policy | Terms of Service | Abuse
Copyright ©2025 elitepvpers All Rights Reserved.