Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

LukasBanana

Alter Hase

  • »LukasBanana« ist der Autor dieses Themas

Beiträge: 1 097

Beruf: Shader Tools Programmer

  • Private Nachricht senden

1

07.07.2014, 22:36

XièXiè 2.0 VirtualMachine (XVM)

Hallo zusammen.
Ich habe zwar schon einen Projek-Thread für meine Programmier-Sprache XièXiè, aber hierbei handelt es sich um ein separates Projekt, das mit der Sprache interagiert.

Hier kurz die Vorgeschichte:
Nach einigen Überlegungen habe ich entschlossen, die Sprache noch mal komplett neu zu spezifizieren und diesmal deutlich einfacher zu halten.
Damit werde ich auch den Compiler noch mal komplett neu schreiben.
Die Sprache soll zwar ähnlich bleiben, aber ich will jede Menge Features raus nehmen, die einfach zu viel für den Anfang sind, z.B. verzichte ich auf Generics und Multiple-Inheritance.
Außerdem beschränke ich mich diesmal auf folgende basis Datentypen: bool, int, float.
Das sollte für eine einfache Script Sprache reichen.

Nun aber zur XVM, der XièXiè VirtualMachine:
Diese habe ich bereits sogut wie fertig und als eigenes Projekt gestartet. Diese ist, im gegensatz zum Compiler, in reinem ANSI C geschrieben.
Warum?
- Weil man für eine virtuelle Maschine keine Objekt Orientierung braucht, da man ohnehin ein Low-Level System entwickelt.
- Weil C schlanken Code produziert (die VM is gerade einmal 14 KB groß).
- Weil C potenziell noch mal einen Tick schneller ist als C++, somal der Code kleiner ist.
- Für das viele Pointer-hacking im low-level Bereich ist C gut geeignet.

Den XASM (XieXie Assembler) Instruction Set habe ich noch mal überarbeitet, für bessere Effizienz und einen simplen Mechanismus, um C und C++ Code mit einzubinden.

Die XVM wird unter der BSD Lizenz veröffentlicht.

Es handelt sich dabei um eine einzelne (knapp 3000 Zeilen) C Datei, die in jedes Projekt eingebunden werden kann.
Das könnte dann so aussehen:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include "xvm.c"

/* ... */

// Read byte code from file
xvm_bytecode byte_code;
xvm_bytecode_init(&byte_code);

if (xvm_bytecode_read_from_file(&byte_code, filename) == 0)
{
    log_readfile_error(filename);
    return 0;
}

// Create stack
size_t stack_size = 512;
xvm_stack stack;
xvm_stack_init(&stack);
xvm_stack_create(&stack, stack_size);

// Execute program
const xvm_exit_codes exit_code = xvm_execute_program(&byte_code, &stack, NULL);

if (exit_code != EXITCODE_SUCCESS)
    log_exitcode_error(exit_code);
else if (verbose != 0)
    log_println("Program terminated successful");

// Clean up
xvm_bytecode_free(&byte_code);
xvm_stack_free(&stack);


Die XVM kann durch einige Macros mit einem Runtime Debuger kompiliert werden.
Das sieht dann z.B. so aus wie im beigefügten Bild.

Und hier noch ein kleines Beispiel zur Assembler Syntax (die XVM wird jedoch nur fertige byte code Dateien lesen können):

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
; Test
; 07/07/2014

        call    Main
        stop                    ; quit
Main:   mov     $r1, @lng0      ; load value of 'lng0'
        add     $sp, 4          ; increase stack for local scope (4 bytes)
        stw     $r1, ($lb) 8    ; store value of $r1 in local scope (after dynamic-link)
        ldw     $r2, str0       ; load address of 'str0'
        xor     $r0, $r0        ; i := 0
        mov     $r1, 10         ; n := 10
.for0:  cmp     $r0, $r1        ; while i < 10
        jge     .end0
        push    $r2
        call    Intr.PrintLn    ; print str0 with new-line
        inc     $r0             ; i++
        jmp     .for0
.end0:  ret     (0) 0           ; return

str0:   .ascii  "Hello, World!"
lng0:   .word   999


Fazit:
Die XVM ist dafür gedacht, falls noch andere (außer mir) für ihre eigene Sprache eine fertige VM suchen,
die sich leicht ins eigene Projekt einbinden lässt.

Ich arbeite gerade am Assembler Compiler, der obiges Code Beispiel in XBC (XièXiè ByteCode) umwandeln kann.
Ansonsten bietet die XVM C Datei Funktionen um Instruktionen zu erzeugen.
Der gesamte Instruction Set ist in der C Datei ausführlich Dokumentiert.

Den Code und fertige Binaries für Windows (vlt. auch für GNU/Linux) werde ich die Tage hier veröffentlichen.
Ich hoffe es besteht ein wenig Interesse :-)

Gruß,
Lukas
»LukasBanana« hat folgendes Bild angehängt:
  • 01 - XVM 2.0 RuntimeDebugger (RTD).png

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »LukasBanana« (08.07.2014, 16:01)


LukasBanana

Alter Hase

  • »LukasBanana« ist der Autor dieses Themas

Beiträge: 1 097

Beruf: Shader Tools Programmer

  • Private Nachricht senden

2

09.07.2014, 13:02

Mir ist gerade aufgefallen, dass die VM sogar reflektiven Code erlaubt ^^

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
; Reflective XASM code
; Program cycle:
;   call main
;   overwrite 4 instructions from 'func' to 'main'
;   push arguments on stack
;   call main again -> this time the code from 'func' will be executed

        call    main
        stop
main:   lda     $r1, @main      ; load address of 'main'
        lda     $r2, @func      ; load address of 'func'
        ldw     $r3, ($r2) 0    ; load first instruction from func[0]
        stw     $r3, ($r1) 0    ; write first instruction to main[0]
        ldw     $r3, ($r2) 4    ; load second instruction from func[1]
        stw     $r3, ($r1) 4    ; ...
        ldw     $r3, ($r2) 8
        stw     $r3, ($r1) 8
        ldw     $r3, ($r2) 12
        stw     $r3, ($r1) 12
        push    10
        call    main
func:   ldw     $r0, ($lb) -4   ; get argument0
        add     $r0, $r0        ; r0 := r0 + r0 (r0 *= 2)
        stw     $r0, ($lb) -4   ; write result back to argument0
        ret     (0) 0

; After execution the code looks like this:

        call    main
        stop
main:   ldw     $r0, ($lb) -4   ; get argument0
        add     $r0, $r0        ; r0 := r0 + r0 (r0 *= 2)
        stw     $r0, ($lb) -4   ; write result back to argument0
        ret     (0) 0           ; return to 'stop' instruction
        ldw     $r3, ($r2) 4    ; ...
        stw     $r3, ($r1) 4
        ldw     $r3, ($r2) 8
        stw     $r3, ($r1) 8
        ldw     $r3, ($r2) 12
        stw     $r3, ($r1) 12
        push    10
        call    main
func:   ldw     $r0, ($lb) -4   ; get argument0
        add     $r0, $r0        ; r0 := r0 + r0 (r0 *= 2)
        stw     $r0, ($lb) -4   ; write result back to argument0
        ret     (0) 0


Aber in welchen Situationen sollte reflektiver Code nützlich sein?
Und wie wird in Hochsprachen reflektiver Code umgesetzt, dass es komfortabel zu benutzen ist?

LukasBanana

Alter Hase

  • »LukasBanana« ist der Autor dieses Themas

Beiträge: 1 097

Beruf: Shader Tools Programmer

  • Private Nachricht senden

3

11.07.2014, 18:18

So jetzt habe ich XVM für Windows und GNU/Linux mal hochgeladen mit zwei kleinen Beispiel Programmen: hello_world.xbc und fibonacci.xbc.
Wie gesagt, die XVM selbst kann nur Byte Code lesen.
An dem Compiler arbeite ich noch. Mit dem Assembler fange ich diesmal an, damit man mit der VM schon mal etwas anfangen kann.

Im folgenden Download sind jede Menge readme Dateien enthalten:

Download: xvm-2.0.zip

Ein kurzes Feedback wäre schön :-)

TrommlBomml

Community-Fossil

Beiträge: 2 117

Wohnort: Berlin

Beruf: Software-Entwickler

  • Private Nachricht senden

4

11.07.2014, 18:53

So sehr ich dein Projekt auch interessant finde, frage ich mich, warum du eine eigene VM implementierst? Klar, ist bestimmt spannend das mal selbst zu bauen, aber ohne JIT-Compiler wirst du da ziemlich Performanceprobleme bekommen. Das hat ja selbst Java irgendwann erkannt.
Also gibt es einen anderen Grund als einen didaktischen, den Compiler/Interpreter selbst zu tippen? Warum baust du das ganze nicht auf LLVM auf? Dann wäre auch bestimmt die Community, die du aufbauen könntest, wesentlich größer. Vor allem, wenn du wirklich was aus der Sprache machen möchtest :).

EDIT: Schade, dass die Original-Sourcen der Programme in XieXie nicht vorliegen, die hätten mich auch interessiert!

LukasBanana

Alter Hase

  • »LukasBanana« ist der Autor dieses Themas

Beiträge: 1 097

Beruf: Shader Tools Programmer

  • Private Nachricht senden

5

11.07.2014, 19:11

Du hast natürlich Recht, richtig performant ist das ohne JiT Compiler nicht.
Für einfache Game-Logic sollte es aber erst mal reichen (eben nicht so umfangreich wie mit MONO C# in Unity).

LLVM wurde uns in zwei Vorlesungseinheiten an der Uni auch mal vorgestellt.
Und damit werde ich mich auf jeden Fall auch noch auseinander setzen :-)
Für x86 Code werde ich definitiv keinen eigenen Code-Generator schreiben ^^

EDIT: Schade, dass die Original-Sourcen der Programme in XieXie nicht vorliegen, die hätten mich auch interessiert!

Die ASM Codes der zwei Beispiele habe ich in die jeweiligen "readme" Dateien gelegt ;-)
Und die Erzeugung dieser Programme ist Teil des "xvm.c" Codes (ganz unten in der Testumgebung).
(EDIT: Weil der Compiler noch in der Mache ist, habe ich diese beiden Programme erst mal von Hand geschrieben.)

Werbeanzeige