0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

2つのアセンブラプログラムが戦うゲームを魔改造。

Last updated at Posted at 2024-10-23

概要

2つのアセンブラプログラムが戦うゲームを見つけたので魔改造してみた。

参考にしたページ

cpuの仕様

レジスタ 3個8bit
Acc アキュムレータ
adr アドレスレジスタ
pc プログラムカウンタ
命令セット 14個12ビット
オペコード4ビット、値8ビット
メモリー 256個12ビット

ニーモニック 意味 コード
hlt pc <- pc 000
ld 12 acc <- 12 10c
ldr acc <- adr 200
str adr <- acc 300
ldm acc <- [adr] 400
stm [adr] <- acc 500
add 12 acc <- acc + 12 60c
sub 12 acc <- acc - 12 70c
gt 12 (acc < 12) ? acc <- 1 : acc <- 0 80c
if 12 (acc = 1) ? pc <- 12 : pc <- pc + 1 90c
jmp 12 pc <- 12 a0c
api alert b00

ゲームの仕様

メモリー上に、プログラムを配置して、起動し、相手のプログラムを破壊した方が、勝ち。

写真

image.png

ブルーのプログラム

90番地に配置、0番地から50番地を2で埋める攻撃。

ld 2
stm
ldr
add 1
str
gt 50
if 90
api
hlt

レッドのプログラム

60番地に配置、80番地から100番地を3で埋める攻撃。

ld 80
str
ld 3
stm
ldr
add 1
str
gt 100
if 62
api
hlt

サンプルコード


const hex3 = (opcode) => ('000' + opcode.toString(16)).slice(-3);

let memory = Array(256).fill(0); 
let programBlue = {
    name: "プログラムブルー",
    adr: 0,
    acc: 0,
    pc: 90,   
    code: [
        "ld 2",   
        "stm",    
        "ldr",  
        "add 1",     
        "str",  
        "gt 50",    
        "if 90",     
        "api",   
        "hlt"       
    ]
};
let programRed = {
    name: "プログラムレッド",
    adr: 0,
    acc: 0,
    pc: 60,    
    code: [
        "ld 80",   
        "str",    
        "ld 3",   
        "stm",    
        "ldr",  
        "add 1",     
        "str",  
        "gt 100",    
        "if 62",     
        "api",   
        "hlt"       
    ]
};
function updateMemoryDisplay() {
    var h = '<table>';
	for (i = 0; i < 256; i = i + 16)
	{
       	h += '<tr>';
        h += '<td>' + hex3(memory[i + 0]) + '<\/td>';
        h += '<td>' + hex3(memory[i + 1]) + '<\/td>';
        h += '<td>' + hex3(memory[i + 2]) + '<\/td>';
        h += '<td>' + hex3(memory[i + 3]) + '<\/td>';
        h += '<td>' + hex3(memory[i + 4]) + '<\/td>';
        h += '<td>' + hex3(memory[i + 5]) + '<\/td>';
        h += '<td>' + hex3(memory[i + 6]) + '<\/td>';
        h += '<td>' + hex3(memory[i + 7]) + '<\/td>';
        h += '<td>' + hex3(memory[i + 8]) + '<\/td>';
        h += '<td>' + hex3(memory[i + 9]) + '<\/td>';
        h += '<td>' + hex3(memory[i + 10]) + '<\/td>';
        h += '<td>' + hex3(memory[i + 11]) + '<\/td>';
        h += '<td>' + hex3(memory[i + 12]) + '<\/td>';
        h += '<td>' + hex3(memory[i + 13]) + '<\/td>';
        h += '<td>' + hex3(memory[i + 14]) + '<\/td>';
        h += '<td>' + hex3(memory[i + 15]) + '<\/td>';
        h += '<\/tr>';
	}
	h += '<\/table>';
	document.getElementById('memory').innerHTML = h;    					
}
function updateProgramDisplay() {
    document.getElementById("blueStatus").innerHTML = `
        現在位置: ${programBlue.pc}, acc: ${programBlue.acc}, adr:  ${programBlue.adr}
        `;
    document.getElementById("redStatus").innerHTML = `
        現在位置: ${programRed.pc}, acc: ${programRed.acc}, adr: ${programRed.adr}
        `;
    document.getElementById("blueInstructions").innerText = programBlue.code.join("\n");
    document.getElementById("redInstructions").innerText = programRed.code.join("\n");
}
function executeInstruction(program) {
    let instruction = memory[program.pc];  
    let opcode = instruction & 0xf00; 
    let opland = instruction & 0xff; 
    switch (opcode) 
    {
    case 0:     //"hlt":
        program.pc--;
    break;
    case 0x100: //"ld":
        program.acc = opland;  
    break;
    case 0x200: //"ldr":
        program.acc = program.adr;  
    break;
    case 0x300: //"str":
        program.adr = program.acc;  
    break;
    case 0x400: //"ldm":
        program.acc = memory[program.adr];  
    break;
    case 0x500: //"stm":
        memory[program.adr] = program.acc;  
    break;
    case 0x600: //"add":
        program.acc += opland;  
    break;
    case 0x700: //"sub":
        program.acc -= opland;  
    break;
    case 0x800: //"gt":
        if (program.acc < opland) 
        {
            program.acc = 1;
        }
        else
        {
            program.acc = 0;
        }
    break;
    case 0x900: //"if":
        if (program.acc == 1) 
        {
            program.pc = opland - 1;  
        }
    break;
    case 0xA00: //"jmp":
        program.pc = opland - 1;  
    break;
    case 0xB00: //"api":
        alert(`${program.name} がゴールしました!`);
    break;
    }
    program.pc++;  
}
function setmem(program) {
    let opcode;
    let adr = program.pc;
    for (i = 0; i < program.code.length; i++)
    {
        let instruction = program.code[i];  
        let parts = instruction.split(" ");  
        let opland = parseInt(parts[1]) & 0xff;
        switch (parts[0]) 
        {
        case "hlt":
            opcode = 0;
            memory[adr] = opcode;
        break;
        case "ld":
            opcode = 1 << 8 | opland;
            memory[adr] = opcode;
        break;
        case "ldr":
            opcode = 2 << 8; 
            memory[adr] = opcode;
        break;
        case "str":
            opcode = 3 << 8;
            memory[adr] = opcode;
        break;
        case "ldm":
            opcode = 4 << 8;
            memory[adr] = opcode;
        break;
        case "stm":
            opcode = 5 << 8;
            memory[adr] = opcode;
        break;
        case "add":
            opcode = 6 << 8 | opland;
            memory[adr] = opcode;
        break;
        case "sub":
            opcode = 7 << 8 | opland;
            memory[adr] = opcode;
        break;
        case "gt":
            opcode = 8 << 8 | opland;
            memory[adr] = opcode;
        break;
        case "if":
            opcode = 9 << 8 | opland;
            memory[adr] = opcode;
        break;
        case "jmp":
            opcode = 10 << 8 | opland;
            memory[adr] = opcode;
        break;
        case "api":
            opcode = 11 << 8;
            memory[adr] = opcode;
        break;
        default:
            alert(instruction);
        }
        adr++;
    }
}
let battleInterval;
function runBattle() {
    battleInterval = setInterval(() => {
        executeInstruction(programBlue);
        executeInstruction(programRed);
        updateMemoryDisplay();
        updateProgramDisplay();
    }, 300);
}
function stopBattle() {
    clearInterval(battleInterval);  
    alert(`終了しました!`);
}
setmem(programBlue);
setmem(programRed);
updateMemoryDisplay();
updateProgramDisplay();




成果物

対戦結果

ブルーのプログラムは、レッドに消された。

image.png

以上。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?