Costruire un sistema informatico con JS? [chiuso]


10

Di recente ho finito questo libro intitolato The Elements of Computing Systems in cui costruisci un sistema operativo funzionante da zero, partendo da porte logiche di base, creando il tuo codice macchina e il linguaggio assembly, fino al codice intermedio e infine un semplice oggetto orientato linguaggio di programmazione che si compila fino al codice VM. Mi è piaciuto molto e mi piacerebbe creare qualcosa di simile in JavaScript, ma con più funzionalità. Ho già scritto un emulatore per la macchina Hack in JS:

  // 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); 
}; 
}; 

Stavo pensando di aggiungere cose come un filesystem, il suono, la connettività Internet e un output dello schermo RGBA (attualmente è solo in bianco e nero). Ma quanto sarebbe fattibile, davvero?

Perché quello che sto pensando di fare è iniziare completamente da zero. E ciò che intendo con ciò è creare il mio codice macchina, quindi lavorare fino a un linguaggio simile a C e creare effettivamente programmi e cose funzionanti.


11
È del tutto fattibile. bellard.org/jslinux
Ingegnere mondiale

4
Provaci e vedi quanto lontano arrivi. Anche se fallisci nel tuo obiettivo finale, sono sicuro che imparerai tonnellate e sembra che questa sia la tua principale motivazione.
James

2
Non usare stringhe, JavaScript supporta numeri interi a 32 bit e operazioni bit a bit su di essi
Esailija

Il numero è l'unica vera parte "cattiva" dell'IMO.
Erik Reppen,

Inoltre, questo mi fa venir voglia di chiedere. Qualche linguaggio interpretato dinamico non ha mai avuto uno strato tra esso e il linguaggio macchina?
Erik Reppen,

Risposte:


2

Potresti sicuramente farlo. Dovresti implementare alcuni componenti del tuo sistema operativo, come il boot loader, e interromperli in una lingua di livello inferiore.

Dai un'occhiata all'approccio adottato dal sistema operativo Singularity di Microsoft su come sviluppare un sistema operativo che gira su Managed Code.

Naturalmente, non è necessario imporre bulloni sulla gestione della memoria a JavaScript, è possibile aggiungere un'API per la gestione della memoria a JavaScript. Puoi scegliere di scrivere un compilatore per JavaScript o di scrivere una macchina virtuale.

Singularity ha a disposizione il codice sorgente in modo da poter ottenere informazioni preziose osservando le decisioni di progettazione prese da Microsoft.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.