Membangun sistem komputer dengan JS? [Tutup]


10

Baru-baru ini saya menyelesaikan buku ini berjudul The Elements of Computing Systems di mana Anda membangun sistem komputer yang berfungsi dari bawah ke atas, mulai dari gerbang logika dasar, hingga membuat kode mesin dan bahasa Assembly, hingga kode perantara, dan akhirnya berorientasi objek sederhana bahasa pemrograman yang mengkompilasi ke kode VM. Saya sangat menikmatinya dan saya ingin membuat sesuatu yang serupa dalam JavaScript, tetapi dengan lebih banyak fitur. Saya sudah menulis sebuah emulator untuk mesin Hack di 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); 
}; 
}; 

Saya sedang berpikir tentang menambahkan hal-hal seperti sistem file, suara, konektivitas Internet, dan output layar RGBA (saat ini hanya hitam dan putih). Tapi seberapa layaknya ini, sungguh?

Karena apa yang saya pikirkan tentang mulai sepenuhnya dari awal. Dan yang saya maksud dengan itu adalah membuat kode mesin saya sendiri, kemudian bekerja sepanjang jalan menuju bahasa C-like dan benar-benar membuat program dan hal-hal yang berfungsi.


11
Sepenuhnya layak. bellard.org/jslinux
World Engineer

4
Pergi saja untuk itu dan lihat seberapa jauh Anda dapatkan. Bahkan jika Anda gagal dalam tujuan akhir Anda, saya yakin Anda akan belajar banyak, dan sepertinya itu adalah motivasi utama Anda.
James

2
Jangan gunakan string, javascript mendukung bilangan bulat 32 bit dan operasi bitwise
Esailija

Angka adalah satu-satunya bagian "buruk" nyata IMO.
Erik Reppen

Juga, ini membuat saya ingin bertanya. Apakah ada bahasa yang ditafsirkan dinamis tidak pernah memiliki lapisan antara itu dan bahasa mesin?
Erik Reppen

Jawaban:


2

Anda tentu bisa melakukannya. Anda harus mengimplementasikan komponen tertentu dari sistem operasi Anda, seperti boot loader, dan menyela dalam bahasa tingkat yang lebih rendah.

Lihat pendekatan yang diambil oleh Singularity Operating System oleh Microsoft tentang cara mengembangkan sistem operasi yang berjalan pada Managed Code.

Tentu saja, tidak ada persyaratan bahwa Anda harus membaut manajemen memori ke JavaScript, Anda dapat menambahkan API untuk manajemen memori ke JavaScript. Anda dapat memilih untuk menulis kompiler untuk JavaScript atau menulis mesin virtual.

Singularity memiliki kode sumber yang tersedia sehingga Anda bisa memperoleh wawasan berharga dari melihat keputusan desain yang dibuat Microsoft.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.