Ein Computersystem mit JS bauen? [geschlossen]

10

Ich habe kürzlich dieses Buch mit dem Titel Die Elemente von Computersystemen fertiggestellt, in dem Sie ein funktionierendes Computersystem von Grund auf aufbauen, angefangen von grundlegenden Logikgattern über die Erstellung Ihres eigenen Maschinencodes und der Assemblersprache bis hin zu Zwischencode und schließlich einem einfachen objektorientierten Programmiersprache, die bis zum VM-Code kompiliert wird. Es hat mir sehr gut gefallen und ich möchte etwas Ähnliches in JavaScript erstellen, aber mit mehr Funktionen. Ich habe bereits einen Emulator für die Hack-Maschine in JS geschrieben:

  // Creates a new CPU object that is responsible for processing instructions
  var CPU = function() {

var D = 0;    // D Register    
var A = 0;    // A Register
var PC = 0;   // Program counter


// Returns whether an instruction is valid or not
var isValidInstruction = function(instruction) {
    if (instruction.length != 32)
        return false;

    instruction = instruction.split(""); 

    for (var c = 0; c < instruction.length; c++)
    {
        if (instruction[c] != "0" && instruction[c] != "1")
            return false;
    }

    return true;
};  


// Given an X and Y input and 6 control bits, returns the ALU output
var computeALU = function(x, y, c) {

    if (c.length != 6)
        throw new Error("There may only be 6 ALU control bits");

    switch (c.join(""))
    {
        case "000000": return 0; 
        case "000001": return 1; 
        case "000010": return -1; 
        case "000011": return x; 
        case "000100": return y; 
        case "000101": return ~x;
        case "000110": return ~y;
        case "000111": return -x; 
        case "001000": return -y; 
        case "001001": return x+1; 
        case "001010": return y+1;
        case "001011": return x-1;
        case "001100": return y-1;
        case "001101": return x+y;
        case "001110": return x-y;
        case "001111": return y-x;
        case "010000": return x*y;
        case "010001": return x/y;
        case "010010": return y/x;
        case "010011": return x%y;
        case "010100": return y%x;
        case "010101": return x&y;
        case "010110": return x|y;
        case "010111": return x^y;
        case "011000": return x>>y;
        case "011001": return y>>x;
        case "011010": return x<<y;
        case "011011": return y<<x;

        default: throw new Error("ALU command " + c.join("") + " not recognized"); 
    }
}; 


// Given an instruction and value of Memory[A], return the result
var processInstruction = function(instruction, M) {

    if (!isValidInstruction(instruction))
        throw new Error("Instruction " + instruction + " is not valid");

    // If this is an A instruction, set value of A register to last 31 bits
    if (instruction[0] == "0")
    {
        A = parseInt(instruction.substring(1, instruction.length), 2);

        PC++; 

        return {
            outM: null,
            addressM: A,
            writeM: false,
            pc: PC
        }; 
    }

    // Otherwise, this could be a variety of instructions
    else
    {
        var instructionType = instruction.substr(0, 3);
        var instructionBody = instruction.substr(3);

        var outputWrite = false; 

        // C Instruction - 100 c1, c2, c3, c4, c5, c6 d1, d2, d3 j1, j2, j3 (000..000 x16)
        if (instructionType == "100")
        {
            var parts = [ "a", "c1", "c2", "c3", "c4", "c5", "c6", "d1", "d2", "d3", "j1", "j2", "j3" ];
            var flags = {}; 

            for (var c = 0; c < parts.length; c++)
                flags[parts[c]] = instructionBody[c]; 

            // Compute the ALU output
            var x = D;
            var y = (flags["a"] == "1") ? M : A; 
            var output = computeALU(x, y, [flags["c1"], flags["c2"], flags["c3"], flags["c4"], flags["c5"], flags["c6"]]); 

            // Store the result
            if (flags["d1"] == "1") A = output; 
            if (flags["d2"] == "1") D = output;
            if (flags["d3"] == "1") outputWrite = true; 

            // Jump if necessary
            if ((flags["j1"] == "1" && output < 0) || (flags["j2"] == "1" && output == 0) || (flags["j3"] == "1" && output > 0)) 
                PC = A;
            else
                PC++; 

            // Return output
            return {
                outM: output,
                addressM: A,
                writeM: outputWrite,
                pc: PC
            }; 
        }

        else throw new Error("Instruction type signature " + instructionType + " not recognized");
    }
}; 


// Reset the CPU by setting all registers back to zero
this.reset = function() {
    D = 0;
    A = 0;
    PC = 0;
}; 


// Set the D register to a specified value
this.setD = function(value) {
    D = value;
}; 


// Set the A register to a specified value
this.setA = function(value) {
    A = value;
}; 


// Set PC to a specified value
this.setPC = function(value) {
    PC = value;
};


// Processes an instruction and returns the result
this.process = function(instruction, M) {
    return processInstruction(instruction, M); 
}; 
}; 

Ich habe darüber nachgedacht, Dinge wie ein Dateisystem, Sound, Internetverbindung und eine RGBA-Bildschirmausgabe hinzuzufügen (derzeit ist es nur Schwarzweiß). Aber wie machbar wäre das wirklich?

Denn was ich überlege, fängt ganz von vorne an. Und damit meine ich, dass ich meinen eigenen Maschinencode erstelle, dann bis zu einer C-ähnlichen Sprache arbeite und tatsächlich Arbeitsprogramme und ähnliches erstelle.

Ryan
quelle
11
Es ist durchaus machbar. bellard.org/jslinux
Welt Ingenieur
4
Probieren Sie es einfach aus und sehen Sie, wie weit Sie kommen. Selbst wenn Sie Ihr Endziel verfehlen, werden Sie sicher Tonnen lernen, und es klingt so, als ob dies Ihre Hauptmotivation ist.
James
2
Verwenden Sie keine Zeichenfolgen, Javascript unterstützt 32-Bit-Ganzzahlen und bitweise Operationen auf ihnen
Esailija
Nummer ist der einzige wirklich "schlechte" Teil IMO.
Erik Reppen
Auch das bringt mich dazu zu fragen. Hat eine dynamisch interpretierte Sprache jemals keine Schicht zwischen ihr und der Maschinensprache gehabt?
Erik Reppen

Antworten:

2

Sie könnten es sicherlich tun. Sie müssten bestimmte Komponenten Ihres Betriebssystems implementieren, z. B. den Bootloader, und Interrupts in einer niedrigeren Sprache.

Sehen Sie sich den Ansatz des Singularity-Betriebssystems von Microsoft an, wie ein Betriebssystem entwickelt wird, das auf verwaltetem Code ausgeführt wird.

Natürlich ist es nicht erforderlich, dass Sie die Speicherverwaltung mit JavaScript verknüpfen müssen. Sie können JavaScript eine API für die Speicherverwaltung hinzufügen. Sie können einen Compiler für JavaScript oder eine virtuelle Maschine schreiben.

Für Singularity steht Quellcode zur Verfügung, sodass Sie wertvolle Einblicke in die von Microsoft getroffenen Entwurfsentscheidungen gewinnen können.

Sam
quelle