開発環境
- OS X El Capitan - Apple (OS)
- Emacs(Text Editor)
- Java (実行環境)
- Python 3.5(プログラミング言語)
コンピュータシステムの理論と実装 (Noam Nisan (著)、Shimon Schocken (著)、斎藤 康毅(翻訳)、オライリージャパン)の6章(アセンブラ)、6.5(プロジェクト)を取り組んでみる。
6.5(プロジェクト)
コード(Emacs)
assembler.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
def commandType(line):
if line[0] == '@':
return 'A_COMMAND'
if line[0] == '(' and line[-1] == ')':
return 'L_COMMAND'
return 'C_COMMAND'
def symbol(line):
type = commandType(line)
if type == 'A_COMMAND':
return line[1:]
if type == 'L_COMMAND':
return line[1:-1]
def dest(line):
i = line.find('=')
if i != -1:
return line[:i]
def comp(line):
i = line.find('=')
if i == -1:
i = -1
j = line.find(';')
if j == -1:
return line[i+1:]
return line[i+1:j]
def jump(line):
i = line.find(';')
if i != -1:
return line[i + 1:]
def dest2bin(dest):
if dest is None:
return '000'
if dest == 'M':
return '001'
if dest == 'D':
return '010'
if dest == 'MD':
return '011'
if dest == 'A':
return '100'
if dest == 'AM':
return '101'
if dest == 'AD':
return '110'
if dest == 'AMD':
return '111'
raise Exception('dest2bin: {0}'.format(dest))
def comp2bin(comp):
if comp == '0':
return '0101010'
if comp == '1':
return '0111111'
if comp == '-1':
return '0111010'
if comp == 'D':
return '0001100'
if comp == 'A':
return '0110000'
if comp == '!D':
return '0001101'
if comp == '!A':
return '0110001'
if comp == '-D':
return '0001111'
if comp == '-A':
return '0110011'
if comp == 'D+1':
return '0011111'
if comp == 'A+1':
return '0110111'
if comp == 'D-1':
return '0001110'
if comp == 'A-1':
return '0110010'
if comp == 'D+A':
return '0000010'
if comp == 'D-A':
return '0010011'
if comp == 'A-D':
return '0000111'
if comp == 'D&A':
return '0000000'
if comp == 'D|A':
return '0010101'
if comp == 'M':
return '1110000'
if comp == '!M':
return '1110001'
if comp == '-M':
return '1110011'
if comp == 'M+1':
return '1110111'
if comp == 'M-1':
return '1110010'
if comp == 'D+M':
return '1000010'
if comp == 'D-M':
return '1010011'
if comp == 'M-D':
return '1000111'
if comp == 'D&M':
return '1000000'
if comp == 'D|M':
return '1010101'
raise Exception("comp2bin: '{0}'".format(comp))
def jump2bin(jump):
if jump == 'JGT':
return '001'
if jump == 'JEQ':
return '010'
if jump == 'JGE':
return '011'
if jump == 'JLT':
return '100'
if jump == 'JNE':
return '101'
if jump == 'JLE':
return '110'
if jump == 'JMP':
return '111'
if jump is None:
return '000'
raise Exception('jump2bin: {0}'.format(jump))
base_addr = 16
symtab = dict(SP=0, LCL=1, ARG=2, THIS=3, THAT=4,
R0=0, R1=1, R2=2, R3=3, R4=4, R5=5, R6=6, R7=7, R8=8, R9=9,
R10=10, R11=11, R12=12, R13=13, R14=14, R15=15,
SCREEN=16384, KBD=24576)
def toBin16bit(n):
s = '0'
for x in range(14, -1, -1):
s += str(n // 2**x)
n = n % 2**x
return s
def is_num(s):
for ch in s:
if '0' <= ch <= '9':
continue
return False
return True
if __name__ == '__main__':
file1 = sys.argv[1]
file2 = file1.replace(".asm", ".hack")
with open(file1) as inf, open(file2, 'w') as outf:
addr = 0
for line in inf:
line = line.strip()
i = line.find('//')
if i != -1:
line = line[0:i].strip()
if line == '':
continue
if commandType(line) == 'L_COMMAND':
symtab[symbol(line)] = addr
else:
addr += 1
inf.seek(0)
for line in inf:
line = line.strip()
i = line.find('//')
if i != -1:
line = line[0:i].strip()
if line == '':
continue
if commandType(line) == 'A_COMMAND':
s = symbol(line)
if is_num(s):
print(toBin16bit(int(s)), file=outf)
else:
if s in symtab:
print(toBin16bit(int(symtab[s])), file=outf)
else:
print(toBin16bit(base_addr), file=outf)
symtab[s] = base_addr
base_addr += 1
elif commandType(line) == 'C_COMMAND':
print('111{comp}{dest}{jump}'.format(
comp=comp2bin(comp(line)), dest=dest2bin(dest(line)),
jump=jump2bin(jump(line))),
file=outf)
0 コメント:
コメントを投稿