目次
前
次
アセンブラ開発
i8048のアセンブラは、PROASM-IIを利用しています。
PROASMは、MS-DOS用アセンブラなので、UnixやMacOSX
では動作しません。
マルチプラットホームのアセンブラを設計、開発して
OSに依存しないアプリケーションプログラムとして
おきます。
RaspberryPiでも使えるように、PythonあるいはAWKを
開発言語としておきます。
AWKを利用して、1バイト、2バイトの命令を
アセンブル処理を記述。
BEGIN {
print "================================="
}
function i2h0(x)
{
xx = "0123456789ABCDEF"
result = substr(xx,x+1,1)
return result
}
function i2h(x)
{
result = i2h0(x/16) i2h0(x%16)
return result
}
{
#code = toupper($0)
# separate
if ( NF == 1 ) {
xx = toupper($1)
l = length(xx)
if ( xx == "NOP" ) { printf("%s -> 00\n",$0) }
if ( xx == "RET" ) { printf("%s -> 83\n",$0) }
if ( xx == "RETR" ) { printf("%s -> 93\n",$0) }
yy = substr(xx,l,1)
if ( yy == ":" ) { printf("%s -> %s\n",$0,substr(xx,1,l-1)) }
}
if ( NF == 2 ) {
opcode = toupper($1)
oprand = toupper($2)
split(oprand,aa,",")
# MOV
if ( opcode == "MOV" ) {
# MOV A
if ( aa[1] == "A" ) {
# MOV A,PSW
if ( aa[2] == "PSW" ) {
x = 199
printf("%s -> %02X\n",$0,x)
}
# MOV A,T
if ( aa[2] == "T" ) {
x = 66
printf("%s -> %02X\n",$0,x)
}
# MOV A,#??
if ( substr(aa[2],1,1) == "#" ) {
if ( substr(aa[2],2,1) == "H" ) {
xx = substr(aa[2],3)
printf("%s -> 23 %s\n",$0,xx)
}
if ( substr(aa[2],2,1) != "H" && aa[2] != "T" ) {
xx = int(substr(aa[2],2))
printf("%s -> 23 %02X\n",$0,xx)
}
}
# MOV A,@RX
if ( substr(aa[2],1,1) == "@" ) {
xx = substr(aa[2],3,1)
x = 240 + int(xx)
printf("%s -> %02X\n",$0,x)
}
# MOV A,RX
if ( substr(aa[2],1,1) == "R" ) {
xx = substr(aa[2],2,1)
x = 248 + int(xx)
printf("%s -> %02X\n",$0,x)
}
}
# MOV RX,A
if ( substr(aa[1],1,1) == "R" && aa[2] == "A" ) {
l = length(aa[1])
xx = substr(aa[1],l,1)
if ( l == 3 ) { x = 160 + int(xx) }
if ( l == 2 ) { x = 168 + int(xx) }
printf("%s -> %02X\n",$0,x)
}
# MOV RX,#*
if ( substr(aa[2],1,1) == "#" && aa[1] != "A" ) {
xx = substr(aa[1],2,1)
x = 184 + int(xx)
if ( substr(aa[2],2,1) == "H" ) {
y = substr(aa[2],3)
printf("%s -> %02X %s\n",$0,x,y)
} else {
yy = int(substr(aa[2],2))
printf("%s -> %02X %02X\n",$0,x,yy)
}
}
}
# MOV PSW,A
if ( aa[1] == "PSW" && aa[2] == "A" ) { printf("%s -> D7\n",$0) }
# MOV T,A
if ( aa[1] == "T" && aa[2] == "A" ) { printf("%s -> 62\n",$0) }
# XCH A
if ( opcode == "XCH" ) {
if ( aa[1] == "A" ) {
l = length( aa[2] )
xx = substr(aa[2],l,1)
if ( l == 3 ) { x = 32 + int(xx) }
if ( l == 2 ) { x = 40 + int(xx) }
printf("%s -> %02X\n",$0,x)
}
}
# ANL , ORL , XRL
if ( opcode == "ANL" || opcode == "ORL" || opcode == "XRL" ) {
if ( aa[1] == "A" && substr(aa[2],1,1) != "#" ) {
l = length( aa[2] )
xx = substr(aa[2],l,1)
if ( opcode == "ANL" ) {
if ( l == 3 ) { x = 80 + int(xx) }
if ( l == 2 ) { x = 88 + int(xx) }
}
if ( opcode == "ORL" ) {
if ( l == 3 ) { x = 64 + int(xx) }
if ( l == 2 ) { x = 72 + int(xx) }
}
if ( opcode == "XRL" ) {
if ( l == 3 ) { x = 208 + int(xx) }
if ( l == 2 ) { x = 216 + int(xx) }
}
printf("%s -> %02X\n",$0,x)
}
if ( aa[1] == "A" && substr(aa[2],1,1) == "#" ) {
if ( opcode == "ANL" ) { x = 83 }
if ( opcode == "ORL" ) { x = 67 }
if ( opcode == "XRL" ) { x = 211 }
if ( substr(aa[2],2,1) == "H" ) {
y = substr(aa[2],3)
printf("%s -> %02X %s\n",$0,x,y)
} else {
yy = int(substr(aa[2],2))
printf("%s -> %02X %02X\n",$0,x,yy)
}
}
if ( aa[1] != "A" && substr(aa[2],1,1) == "#" ) {
if ( aa[1] == "BUS" ) { xx = 0 }
if ( substr(aa[1],1,1) == "P" ) { xx = substr(aa[1],2,1) }
if ( opcode == "ANL" ) { x = 152 + int(xx) }
if ( opcode == "ORL" ) { x = 136 + int(xx) }
if ( substr(aa[2],2,1) == "H" ) {
y = substr(aa[2],3)
printf("%s -> %02X %s\n",$0,x,y)
} else {
yy = int(substr(aa[2],2))
printf("%s -> %02X %02X\n",$0,x,yy)
}
}
}
# ADD A , ADDC A
if ( opcode == "ADD" || opcode == "ADDC" ) {
if ( aa[1] == "A" && substr(aa[2],1,1) != "#" ) {
l = length( aa[2] )
xx = substr(aa[2],l,1)
if ( opcode == "ADD" ) {
if ( l == 3 ) { x = 96 + int(xx) }
if ( l == 2 ) { x = 104 + int(xx) }
}
if ( opcode == "ADDC" ) {
if ( l == 3 ) { x = 112 + int(xx) }
if ( l == 2 ) { x = 120 + int(xx) }
}
printf("%s -> %02X\n",$0,x)
}
if ( aa[1] == "A" && substr(aa[2],1,1) == "#" ) {
if ( opcode == "ADD" ) { x = 3 }
if ( opcode == "ADDC" ) { x = 19 }
if ( substr(aa[2],2,1) == "H" ) {
y = substr(aa[2],3)
printf("%s -> %02X %s\n",$0,x,y)
} else {
yy = int(substr(aa[2],2))
printf("%s -> %02X %02X\n",$0,x,yy)
}
}
}
# INC , DEC
if ( opcode == "INC" || opcode == "DEC" ) {
l = length( aa[1] )
xx = substr(aa[1],l,1)
if ( opcode == "INC" ) {
if ( l == 1 ) { x = 23 }
if ( l == 2 ) { x = 24 + int(xx) }
if ( l == 3 ) { x = 16 + int(xx) }
}
if ( opcode == "DEC" ) {
if ( l == 1 ) { x = 7 }
if ( l == 2 ) { x = 200 + int(xx) }
}
printf("%s -> %02X\n",$0,x)
}
# CLR
if ( opcode == "CLR" ) {
if ( oprand == "A" ) { x = 39 }
if ( oprand == "C" ) { x = 151 }
printf("%s -> %02X\n",$0,x)
}
# CPL
if ( opcode == "CPL" ) {
if ( oprand == "A" ) { x = 55 }
if ( oprand == "C" ) { x = 167 }
if ( oprand == "F0" ) { x = 149 }
if ( oprand == "F1" ) { x = 181 }
printf("%s -> %02X\n",$0,x)
}
# DA
if ( opcode == "DA" ) {
if ( oprand == "A" ) { x = 87 }
printf("%s -> %02X\n",$0,x)
}
# SWAP
if ( opcode == "SWAP" ) {
if ( oprand == "A" ) { x = 71 }
printf("%s -> %02X\n",$0,x)
}
# RL
if ( opcode == "RL" ) {
if ( oprand == "A" ) { x = 231 }
printf("%s -> %02X\n",$0,x)
}
# RLC
if ( opcode == "RLC" ) {
if ( oprand == "A" ) { x = 247 }
printf("%s -> %02X\n",$0,x)
}
# RR
if ( opcode == "RR" ) {
if ( oprand == "A" ) { x = 119 }
printf("%s -> %02X\n",$0,x)
}
# RRC
if ( opcode == "RRC" ) {
if ( oprand == "A" ) { x = 103 }
printf("%s -> %02X\n",$0,x)
}
# IN
if ( opcode == "IN" ) {
if ( aa[1] == "A" ) {
l = length(aa[2])
xx = substr(aa[2],l,1)
x = 8 + int(xx)
}
printf("%s -> %02X\n",$0,x)
}
# OUTL
if ( opcode == "OUTL" ) {
if ( aa[2] == "A" && substr(aa[1],1,1) == "P" ) {
l = length(aa[1])
xx = substr(aa[1],l,1)
x = 56 + int(xx)
printf("%s -> %02X\n",$0,x)
}
if ( aa[2] == "A" && aa[1] == "BUS" ) {
printf("%s -> 02\n",$0)
}
}
# INS
if ( opcode == "INS" ) {
if ( aa[1] == "A" && aa[2] == "BUS" ) {
printf("%s -> 08\n",$0)
}
}
# SEL
if ( opcode == "SEL" ) {
if ( oprand == "RB0" ) { x = 197 }
if ( oprand == "RB1" ) { x = 213 }
if ( oprand == "MB0" ) { x = 229 }
if ( oprand == "MB1" ) { x = 245 }
printf("%s -> %02X\n",$0,x)
}
# ENT0 CLK
if ( opcode == "ENT0" ) {
if ( oprand == "CLK" ) { x = 117 }
printf("%s -> %02X\n",$0,x)
}
# STRT
if ( opcode == "STRT" ) {
if ( oprand == "T" ) { x = 85 }
if ( oprand == "CNT" ) { x = 69 }
printf("%s -> %02X\n",$0,x)
}
# STOP
if ( opcode == "STOP" ) {
if ( oprand == "TCNT" ) { x = 101 }
printf("%s -> %02X\n",$0,x)
}
# EN
if ( opcode == "EN" ) {
if ( oprand == "I" ) { x = 5 }
if ( oprand == "TCNTI" ) { x = 37 }
printf("%s -> %02X\n",$0,x)
}
# DIS
if ( opcode == "DIS" ) {
if ( oprand == "I" ) { x = 21 }
if ( oprand == "TCNTI" ) { x = 53 }
printf("%s -> %02X\n",$0,x)
}
# CALL
if ( opcode == "CALL" ) {
x = 20
printf("%s -> %02X ??\n",$0,x)
}
# DJNZ
if ( opcode == "DJNZ" ) {
xx = substr(aa[1],2,1)
x = 232 + int(xx)
printf("%s -> %02X ??\n",$0,x)
}
# JC
if ( opcode == "JC" ) {
x = 246
printf("%s -> %02X ??\n",$0,x)
}
# JNC
if ( opcode == "JNC" ) {
x = 230
printf("%s -> %02X ??\n",$0,x)
}
# JZ
if ( opcode == "JZ" ) {
x = 198
printf("%s -> %02X ??\n",$0,x)
}
# JNZ
if ( opcode == "JNZ" ) {
x = 150
printf("%s -> %02X ??\n",$0,x)
}
# JT0
if ( opcode == "JT0" ) {
x = 54
printf("%s -> %02X ??\n",$0,x)
}
# JNT0
if ( opcode == "JNT0" ) {
x = 38
printf("%s -> %02X ??\n",$0,x)
}
# JT1
if ( opcode == "JT1" ) {
x = 86
printf("%s -> %02X ??\n",$0,x)
}
# JNT1
if ( opcode == "JNT1" ) {
x = 70
printf("%s -> %02X ??\n",$0,x)
}
# JF0
if ( opcode == "JF0" ) {
x = 182
printf("%s -> %02X ??\n",$0,x)
}
# JF1
if ( opcode == "JF1" ) {
x = 118
printf("%s -> %02X ??\n",$0,x)
}
}
}
END {
print "================================="
}
1バイト、2バイトの命令を弁別するだけの
ソースコードを書いて、アセンブラが正しく
動作しているかを確認してみます。
ソースコードは、以下。
mov a,#12
mov a,#h12
mov a,@r0
mov a,@r1
mov a,r0
mov a,r1
mov a,r2
mov a,r3
mov a,r4
mov a,r5
mov a,r6
mov a,r7
mov a,psw
mov psw,a
xch a,@R0
xch a,@R1
xch a,R0
xch a,R1
xch a,R2
xch a,R3
xch a,R4
xch a,R5
xch a,R6
xch a,R7
mov @r0,a
mov @r1,a
mov r0,a
mov r1,a
mov r2,a
mov r3,a
mov r4,a
mov r5,a
mov r6,a
mov r7,a
mov r0,#00
mov r1,#01
mov r2,#hF0
mov r3,#hF1
mov r4,#00
mov r5,#01
mov r6,#hF0
mov r7,#hF1
anl a,@R0
anl a,@R1
anl a,R0
anl a,R1
anl a,R2
anl a,R3
anl a,R4
anl a,R5
anl a,R6
anl a,R7
anl a,#21
anl a,#h12
orl a,@R0
orl a,@R1
orl a,R0
orl a,R1
orl a,R2
orl a,R3
orl a,R4
orl a,R5
orl a,R6
orl a,R7
orl a,#21
orl a,#h12
xrl a,@R0
xrl a,@R1
xrl a,R0
xrl a,R1
xrl a,R2
xrl a,R3
xrl a,R4
xrl a,R5
xrl a,R6
xrl a,R7
xrl a,#21
xrl a,#h12
add a,@R0
add a,@R1
add a,R0
add a,R1
add a,R2
add a,R3
add a,R4
add a,R5
add a,R6
add a,R7
add a,#21
add a,#h12
addc a,@R0
addc a,@R1
addc a,R0
addc a,R1
addc a,R2
addc a,R3
addc a,R4
addc a,R5
addc a,R6
addc a,R7
addc a,#21
addc a,#h12
inc a
inc @R0
inc @R1
inc R0
inc R1
inc R2
inc R3
inc R4
inc R5
inc R6
inc R7
dec a
dec R0
dec R1
dec R2
dec R3
dec R4
dec R5
dec R6
dec R7
clr a
clr c
cpl a
cpl c
cpl f0
cpl f1
da a
swap a
rl a
rlc a
rr a
rrc a
in a,P1
in a,P2
outl P1,a
outl P2,a
anl P1,#12
anl P2,#h12
anl bus,#12
anl bus,#h12
orl P1,#12
orl P2,#h12
orl bus,#12
orl bus,#h12
ins a,bus
outl bus,a
sel rb0
sel rb1
sel mb0
sel mb1
ent0 clk
mov a,t
mov t,a
strt t
strt cnt
stop tcnt
en i
dis i
en tcnti
dis tcnti
nop
ret
retr
jc x
jnc x
jz x
jnz x
jt0 x
jnt0 x
jt1 x
jnt1 x
jf0 x
jf1 x
djnz r0,x
djnz r1,x
djnz r2,x
djnz r3,x
djnz r4,x
djnz r5,x
djnz r6,x
djnz r7,x
call xxx
L:
main:
loop:
アセンブル結果は、次のようになりました。
=================================
mov a,#12 -> 23 0C
mov a,#h12 -> 23 12
mov a,@r0 -> F0
mov a,@r1 -> F1
mov a,r0 -> F8
mov a,r1 -> F9
mov a,r2 -> FA
mov a,r3 -> FB
mov a,r4 -> FC
mov a,r5 -> FD
mov a,r6 -> FE
mov a,r7 -> FF
mov a,psw -> C7
mov psw,a -> D7
xch a,@R0 -> 20
xch a,@R1 -> 21
xch a,R0 -> 28
xch a,R1 -> 29
xch a,R2 -> 2A
xch a,R3 -> 2B
xch a,R4 -> 2C
xch a,R5 -> 2D
xch a,R6 -> 2E
xch a,R7 -> 2F
mov r0,a -> A8
mov r1,a -> A9
mov r2,a -> AA
mov r3,a -> AB
mov r4,a -> AC
mov r5,a -> AD
mov r6,a -> AE
mov r7,a -> AF
mov r0,#00 -> B8 00
mov r1,#01 -> B9 01
mov r2,#hF0 -> BA F0
mov r3,#hF1 -> BB F1
mov r4,#00 -> BC 00
mov r5,#01 -> BD 01
mov r6,#hF0 -> BE F0
mov r7,#hF1 -> BF F1
anl a,@R0 -> 50
anl a,@R1 -> 51
anl a,R0 -> 58
anl a,R1 -> 59
anl a,R2 -> 5A
anl a,R3 -> 5B
anl a,R4 -> 5C
anl a,R5 -> 5D
anl a,R6 -> 5E
anl a,R7 -> 5F
anl a,#21 -> 53 15
anl a,#h12 -> 53 12
orl a,@R0 -> 40
orl a,@R1 -> 41
orl a,R0 -> 48
orl a,R1 -> 49
orl a,R2 -> 4A
orl a,R3 -> 4B
orl a,R4 -> 4C
orl a,R5 -> 4D
orl a,R6 -> 4E
orl a,R7 -> 4F
orl a,#21 -> 43 15
orl a,#h12 -> 43 12
xrl a,@R0 -> D0
xrl a,@R1 -> D1
xrl a,R0 -> D8
xrl a,R1 -> D9
xrl a,R2 -> DA
xrl a,R3 -> DB
xrl a,R4 -> DC
xrl a,R5 -> DD
xrl a,R6 -> DE
xrl a,R7 -> DF
xrl a,#21 -> D3 15
xrl a,#h12 -> D3 12
add a,@R0 -> 60
add a,@R1 -> 61
add a,R0 -> 68
add a,R1 -> 69
add a,R2 -> 6A
add a,R3 -> 6B
add a,R4 -> 6C
add a,R5 -> 6D
add a,R6 -> 6E
add a,R7 -> 6F
add a,#21 -> 03 15
add a,#h12 -> 03 12
addc a,@R0 -> 70
addc a,@R1 -> 71
addc a,R0 -> 78
addc a,R1 -> 79
addc a,R2 -> 7A
addc a,R3 -> 7B
addc a,R4 -> 7C
addc a,R5 -> 7D
addc a,R6 -> 7E
addc a,R7 -> 7F
addc a,#21 -> 13 15
addc a,#h12 -> 13 12
inc a -> 17
inc @R0 -> 10
inc @R1 -> 11
inc R0 -> 18
inc R1 -> 19
inc R2 -> 1A
inc R3 -> 1B
inc R4 -> 1C
inc R5 -> 1D
inc R6 -> 1E
inc R7 -> 1F
dec a -> 07
dec R0 -> C8
dec R1 -> C9
dec R2 -> CA
dec R3 -> CB
dec R4 -> CC
dec R5 -> CD
dec R6 -> CE
dec R7 -> CF
clr a -> 27
clr c -> 97
cpl a -> 37
cpl c -> A7
cpl f0 -> 95
cpl f1 -> B5
da a -> 57
swap a -> 47
rl a -> E7
rlc a -> F7
rr a -> 77
rrc a -> 67
in a,P1 -> 09
in a,P2 -> 0A
outl P1,a -> 39
outl P2,a -> 3A
anl P1,#12 -> 99 0C
anl P2,#h12 -> 9A 12
anl bus,#12 -> 98 0C
anl bus,#h12 -> 98 12
orl P1,#12 -> 89 0C
orl P2,#h12 -> 8A 12
orl bus,#12 -> 88 0C
orl bus,#h12 -> 88 12
ins a,bus -> 08
outl bus,a -> 02
sel rb0 -> C5
sel rb1 -> D5
sel mb0 -> E5
sel mb1 -> F5
ent0 clk -> 75
mov a,t -> 42
mov t,a -> 62
strt t -> 55
strt cnt -> 45
stop tcnt -> 65
en i -> 05
dis i -> 15
en tcnti -> 25
dis tcnti -> 35
nop -> 00
ret -> 83
retr -> 93
jc x -> F6 ??
jnc x -> E6 ??
jz x -> C6 ??
jnz x -> 96 ??
jt0 x -> 36 ??
jnt0 x -> 26 ??
jt1 x -> 56 ??
jnt1 x -> 46 ??
jf0 x -> B6 ??
jf1 x -> 76 ??
djnz r0,x -> E8 ??
djnz r1,x -> E9 ??
djnz r2,x -> EA ??
djnz r3,x -> EB ??
djnz r4,x -> EC ??
djnz r5,x -> ED ??
djnz r6,x -> EE ??
djnz r7,x -> EF ??
L: -> L
main: -> MAIN
loop: -> LOOP
=================================
イミディエイト、分岐の命令だけが2バイトと
なることを理解できました。
AWKでは16進数で扱わないで、最後に変換して
わかりやすくしておきました。
極力PROASMのアセンブリ言語のフォーマットに
近づけたいですが、16進数、10進数の指定には
数字の前に、Hをつけるかどうかで判定する仕様。
処理ロジックがわかれば、Pythonで実現するために
必要な関数、手続きを定義して、使うようにします。
闇雲に開発すると、余計な時間をかけることが多い
ので、設計仕様を固めておきます。
- 2パスでアセンブラとする
- 1パス目で、擬似命令と機械語を扱う
- 2パス目で、ラベルを実アドレスに変換してHEXファイルを生成
- ディレイティブ(擬似命令)は、サフィックスに「.」(ドット)をつける
- ディレイティブは、.EQU、.ORG、.ENDに限定
- 16進数は、先頭にhかHをつける
- 2進数は、先頭にbかBをつける
- 分岐先のラベルには、先頭に「:」(コロン)をつける
- 変換はテーブル参照を利用
テーブル参照を使うには、Pythonで扱える連想配列を活用。
連想配列は、次のように宣言して活用
.EQU -> tblequ
.ORG -> tblorg
.END -> tblend
(under construction)
目次
前
次