¿Construyendo un sistema informático con JS? [cerrado]

10

Recientemente terminé este libro llamado The Elements of Computing Systems donde construyes un sistema informático que funciona desde cero, comenzando desde puertas lógicas básicas, hasta crear tu propio código de máquina y lenguaje ensamblador, hasta código intermedio y finalmente un simple orientado a objetos. lenguaje de programación que se compila en código VM. Lo disfruté mucho y me gustaría crear algo similar en JavaScript, pero con más funciones. Ya escribí un emulador para la máquina Hack en 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); 
}; 
}; 

Estaba pensando en agregar cosas como un sistema de archivos, sonido, conectividad a Internet y una salida de pantalla RGBA (actualmente solo es en blanco y negro). Pero, ¿qué tan factible sería esto realmente?

Porque lo que estoy pensando en hacer es comenzar completamente desde cero. Y lo que quiero decir con eso es crear mi propio código de máquina, luego trabajar todo el camino hacia un lenguaje tipo C y, de hecho, crear programas de trabajo y esas cosas.

Ryan
fuente
11
Es completamente factible. bellard.org/jslinux
Ingeniero mundial
44
Simplemente ve y ve qué tan lejos llegas. Incluso si fallas en tu objetivo final, estoy seguro de que aprenderás toneladas, y parece que esa es tu principal motivación.
James
2
No use cadenas, javascript admite enteros de 32 bits y operaciones bit a bit en ellos
Esailija
El número es la única parte "mala" real de la OMI.
Erik Reppen
Además, esto me da ganas de preguntar. ¿Algún lenguaje interpretado dinámico alguna vez no tuvo una capa entre este y el lenguaje máquina?
Erik Reppen

Respuestas:

2

Ciertamente podrías hacerlo. Debería implementar ciertos componentes de su sistema operativo, como el cargador de arranque, e interrumpir en un lenguaje de nivel inferior.

Eche un vistazo al enfoque adoptado por el sistema operativo Singularity de Microsoft sobre cómo desarrollar un sistema operativo que se ejecute en código administrado.

Por supuesto, no hay ningún requisito de que deba atornillar la administración de memoria a JavaScript, puede agregar una API para la administración de memoria a JavaScript. Puede elegir escribir un compilador para JavaScript o escribir una máquina virtual.

Singularity tiene disponible el código fuente para que pueda obtener información valiosa al observar las decisiones de diseño que tomó Microsoft.

Sam
fuente