Last active
August 29, 2015 14:12
-
-
Save silverweed/aa1efadf128d3e1505b0 to your computer and use it in GitHub Desktop.
From challenge http://www.reddit.com/r/dailyprogrammer/comments/1kqxz9/080813_challenge_132_intermediate_tiny_assembler/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- generate random assembly for tiny | |
opcodes = { | |
{{ 'AND', 'm', 'm' }, { 'AND', 'm', 'c' }}, | |
{{ 'OR', 'm', 'm' }, { 'OR', 'm', 'c' }}, | |
{{ 'XOR', 'm', 'm' }, { 'XOR', 'm', 'c' }}, | |
{{ 'NOT', 'm' }}, | |
{{ 'MOV', 'm', 'm' }, { 'MOV', 'm', 'c' }}, | |
{{ 'RANDOM', 'm' }}, | |
{{ 'ADD', 'm', 'm' }, { 'ADD', 'm', 'c' }}, | |
{{ 'SUB', 'm', 'm' }, { 'SUB', 'm', 'c' }}, | |
{{ 'APRINT', 'm' }, { 'APRINT', 'c' }}, | |
{{ 'DPRINT', 'm' }, { 'DPRINT', 'c' }}, | |
} | |
for i = 0, 10000, 1 do | |
local op = opcodes[math.random(#opcodes)] | |
local optype = op[math.random(#op)] | |
io.write(optype[1], " "); | |
for j = 2, #optype, 1 do | |
if optype[j] == 'c' then | |
io.write(math.random(255)) | |
else | |
io.write("[", math.random(255), "]") | |
end | |
io.write(" ") | |
end | |
print("") | |
end | |
print("HALT") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{- Assembler for the tiny assembly language | |
- (see http://www.reddit.com/r/dailyprogrammer/comments/1kqxz9/080813_challenge_132_intermediate_tiny_assembler/) | |
- by silverweed | |
-} | |
import Data.Char (toUpper) | |
import Data.Word | |
import System.IO | |
import qualified Data.ByteString as B | |
data ParamType = Const Int | Mem Int | |
data ParamList = | |
NoParams | |
| OneParam ParamType | |
| TwoParams ParamType ParamType | |
| ThreeParams ParamType ParamType ParamType | |
parseType :: String -> ParamType | |
parseType s@('[':v) | |
| last v == ']' = Mem $ read $ init v | |
| otherwise = error ("Invalid operand: " ++ s) | |
parseType v = Const $ read v | |
get :: String -> (String, ParamList) | |
get line = | |
case len of | |
1 -> (op, NoParams) | |
2 -> (op, OneParam p1) | |
where | |
p1 = parseType $ par !! 0 | |
3 -> (op, TwoParams p1 p2) | |
where | |
p1 = parseType $ par !! 0 | |
p2 = parseType $ par !! 1 | |
4 -> (op, ThreeParams p1 p2 p3) | |
where | |
p1 = parseType $ par !! 0 | |
p2 = parseType $ par !! 1 | |
p3 = parseType $ par !! 2 | |
where | |
spl = words line | |
len = length spl | |
op = map toUpper $ head spl | |
par = tail spl | |
emitCode :: (String, ParamList) -> [Word8] | |
emitCode x = map fromIntegral $ encode x | |
where | |
encode ("AND", TwoParams (Mem a) (Mem b)) = [0x00, a, b] | |
encode ("AND", TwoParams (Mem a) (Const b)) = [0x01, a, b] | |
encode ("OR", TwoParams (Mem a) (Mem b)) = [0x02, a, b] | |
encode ("OR", TwoParams (Mem a) (Const b)) = [0x03, a, b] | |
encode ("XOR", TwoParams (Mem a) (Mem b)) = [0x04, a, b] | |
encode ("XOR", TwoParams (Mem a) (Const b)) = [0x05, a, b] | |
encode ("NOT", OneParam (Mem a)) = [0x06, a] | |
encode ("MOV", TwoParams (Mem a) (Mem b)) = [0x07, a, b] | |
encode ("MOV", TwoParams (Mem a) (Const b)) = [0x08, a, b] | |
encode ("RANDOM", OneParam (Mem a)) = [0x09, a] | |
encode ("ADD", TwoParams (Mem a) (Mem b)) = [0x0a, a, b] | |
encode ("ADD", TwoParams (Mem a) (Const b)) = [0x0b, a, b] | |
encode ("SUB", TwoParams (Mem a) (Mem b)) = [0x0c, a, b] | |
encode ("SUB", TwoParams (Mem a) (Const b)) = [0x0d, a, b] | |
encode ("JMP", OneParam (Mem a)) = [0x0e, a] | |
encode ("JMP", OneParam (Const a)) = [0x0f, a] | |
encode ("JZ", TwoParams (Mem a) (Mem b)) = [0x10, a, b] | |
encode ("JZ", TwoParams (Mem a) (Const b)) = [0x11, a, b] | |
encode ("JZ", TwoParams (Const a) (Mem b)) = [0x12, a, b] | |
encode ("JZ", TwoParams (Const a) (Const b)) = [0x13, a, b] | |
encode ("JEQ", ThreeParams (Mem a) (Mem b) (Mem c)) = [0x14, a, b, c] | |
encode ("JEQ", ThreeParams (Const a) (Mem b) (Mem c)) = [0x15, a, b, c] | |
encode ("JEQ", ThreeParams (Mem a) (Mem b) (Const c)) = [0x16, a, b, c] | |
encode ("JEQ", ThreeParams (Const a) (Mem b) (Const c)) = [0x17, a, b, c] | |
encode ("JLS", ThreeParams (Mem a) (Mem b) (Mem c)) = [0x18, a, b, c] | |
encode ("JLS", ThreeParams (Const a) (Mem b) (Mem c)) = [0x19, a, b, c] | |
encode ("JLS", ThreeParams (Mem a) (Mem b) (Const c)) = [0x1a, a, b, c] | |
encode ("JLS", ThreeParams (Const a) (Mem b) (Const c)) = [0x1b, a, b, c] | |
encode ("JGT", ThreeParams (Mem a) (Mem b) (Mem c)) = [0x1c, a, b, c] | |
encode ("JGT", ThreeParams (Const a) (Mem b) (Mem c)) = [0x1d, a, b, c] | |
encode ("JGT", ThreeParams (Mem a) (Mem b) (Const c)) = [0x1e, a, b, c] | |
encode ("JGT", ThreeParams (Const a) (Mem b) (Const c)) = [0x1f, a, b, c] | |
encode ("HALT", NoParams) = [0xff] | |
encode ("APRINT", OneParam (Mem a)) = [0x20, a] | |
encode ("APRINT", OneParam (Const a)) = [0x21, a] | |
encode ("DPRINT", OneParam (Mem a)) = [0x22, a] | |
encode ("DPRINT", OneParam (Const a)) = [0x23, a] | |
encode (x, _) = error ("Invalid line: " ++ x) | |
readLine :: Bool -> IO () | |
readLine True = return () | |
readLine False = do | |
line <- getLine | |
B.putStr $ B.pack $ emitCode $ get line | |
isEOF >>= readLine | |
main = isEOF >>= readLine |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// written by Hamcha (https://github.com/hamcha) | |
use std::rand; | |
fn execute(code: Vec<u8>) { | |
let length = code.len(); | |
let mut memory = [0u8; 256]; | |
let mut offset = 0u; | |
while offset < length { | |
let opcode = code[offset]; | |
match opcode { | |
// AND | |
0x00 | 0x01 => { | |
let (a, b) = (code[offset + 1], code[offset + 2]); | |
let op = if opcode & 1 < 1 { memory[b as uint] } else { b }; | |
memory[a as uint] &= op; | |
offset += 2; | |
} | |
// OR | |
0x02 | 0x03 => { | |
let (a, b) = (code[offset + 1], code[offset + 2]); | |
let op = if opcode & 1 < 1 { memory[b as uint] } else { b }; | |
memory[a as uint] |= op; | |
offset += 2; | |
} | |
// XOR | |
0x04 | 0x05 => { | |
let (a, b) = (code[offset + 1], code[offset + 2]); | |
let op = if opcode & 1 < 1 { memory[b as uint] } else { b }; | |
memory[a as uint] ^= op; | |
offset += 2; | |
} | |
// NOT | |
0x06 => { | |
let a = code[offset + 1]; | |
memory[a as uint] ^= 0xff; | |
offset += 1; | |
} | |
// MOV | |
0x07 | 0x08 => { | |
let (a, b) = (code[offset + 1], code[offset + 2]); | |
let op = if opcode & 1 > 0 { memory[b as uint] } else { b }; | |
memory[a as uint] = op; | |
offset += 2; | |
} | |
// RANDOM | |
0x09 => { | |
let a = code[offset + 1]; | |
memory[a as uint] = rand::random::<u8>() % 26; | |
offset += 1; | |
} | |
// ADD | |
0x0a | 0x0b => { | |
let (a, b) = (code[offset + 1], code[offset + 2]); | |
let op = if opcode & 1 < 1 { memory[b as uint] } else { b }; | |
memory[a as uint] += op; | |
offset += 2; | |
} | |
// SUB | |
0x0c | 0x0d => { | |
let (a, b) = (code[offset + 1], code[offset + 2]); | |
let op = if opcode & 1 < 1 { memory[b as uint] } else { b }; | |
memory[a as uint] -= op; | |
offset += 2; | |
} | |
// JMP | |
0x0e | 0x0f => { | |
let a = code[offset + 1]; | |
let addr = if opcode & 1 < 1 { memory[a as uint] } else { a }; | |
offset = (addr as uint) - 1; | |
} | |
// JZ | |
0x10 | 0x11 | 0x12 | 0x13 => { | |
let (a, b) = (code[offset + 1], code[offset + 2]); | |
let addr = if opcode < 0x12 { memory[a as uint] } else { a }; | |
let op = if opcode & 1 < 1 { memory[b as uint] } else { b }; | |
offset = if op == 0 { (addr as uint) - 1 } else { offset + 2 }; | |
} | |
// JEQ | |
0x14 | 0x15 | 0x16 | 0x17 => { | |
let (a, b, c) = (code[offset + 1], code[offset + 2], code[offset + 3]); | |
let addr = if opcode < 0x16 { memory[a as uint] } else { a }; | |
let op = if opcode & 1 < 1 { memory[c as uint] } else { c }; | |
offset = if op == memory[b as uint] { (addr as uint) - 1 } else { offset + 3 }; | |
} | |
// JLS | |
0x18 | 0x19 | 0x1a | 0x1b => { | |
let (a, b, c) = (code[offset + 1], code[offset + 2], code[offset + 3]); | |
let addr = if opcode < 0x1a { memory[a as uint] } else { a }; | |
let op = if opcode & 1 < 1 { memory[c as uint] } else { c }; | |
offset = if op > memory[b as uint] { (addr as uint) - 1 } else { offset + 3 }; | |
} | |
// JGT | |
0x1c | 0x1d | 0x1e | 0x1f => { | |
let (a, b, c) = (code[offset + 1], code[offset + 2], code[offset + 3]); | |
let addr = if opcode < 0x1e { memory[a as uint] } else { a }; | |
let op = if opcode & 1 < 1 { memory[c as uint] } else { c }; | |
offset = if op < memory[b as uint] { (addr as uint) - 1 } else { offset + 3 }; | |
} | |
// APRINT, DPRINT | |
0x20 | 0x21 | 0x22 | 0x23 => { | |
let a = code[offset + 1]; | |
let op = if opcode & 1 < 1 { memory[a as uint] } else { a }; | |
if opcode < 0x22 { | |
println!("{}",op as char); | |
} else { | |
println!("{}",op as u8); | |
} | |
offset += 1; | |
} | |
// HALT | |
0xff => { break } | |
_ => println!("Unknown opcode: {}", opcode) | |
} | |
offset += 1; | |
} | |
println!("\nFinished execution, dumping RAM.."); | |
for i in range(0u, 256u) { | |
if i % 16 < 1 { | |
println!(""); | |
if i < 0x10 { | |
print!("0"); | |
} | |
print!("{:X} : ", i); | |
} | |
if memory[i] < 0x10 { | |
print!("0"); | |
} | |
print!("{:X} ", memory[i]); | |
} | |
println!(""); | |
} | |
fn main() { | |
let code = std::io::stdin().read_to_end().ok().expect("Can't read from STDIN"); | |
execute(code); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment