わらばんし仄聞記

南の国で引きこもってるWeb屋さん

intel-8086データシート

intel 8086のデータシートを読んでてちょくちょくと詰まった所があったので、それのメモ。
読んでた箇所は"Table2. Instruction Set Summary"で、MOV命令の箇所。どういうビット列がどの命令と解釈されるかと、特定の役割を持ったビットの説明について。

命令表

とりあえず、問題の命令表はこんな感じ

MOV命令

76543210 76543210 76543210 76543210
Register/Memory to/from Register 100010dw mod reg r/m
Immediate to Register/memory 1100011w mod 000 r/m data data if w = 1
Immediate to Register 1011 w reg data data if w = 1
Memory to Accumulator 1010000w addr-low addr-high
Accumulator to Memory 1010001w addr-low addr-high
Register/Memory to Segment Register 10001110 mod 0 reg r/m
Segment Register to Register/Memory 10001100 mod 0 reg r/m

MOV命令はどういうビットで成り立っているかがこれよりわかる。なんか表が崩れたりするし、実際にどう書かれているかはデータシートそのものを見てもらった方がいい。
例えば"Register/Memory to/from Register"、つまりは、レジスタかメモリのどちらかからレジスタへの値のコピー。またはレジスタかメモリのどちらかへ、レジスタから値をコピーする命令は"100010"というビットで始まり、以降の10ビットによりメモリかレジスタかといったことや、レジスタならどのレジスタかという事を指定する。

ここで各命令の挙動を指定するビットである、"mod"や"r/m"やらの説明がデータシートの最終ページにあり、それらと合わせてビット列を読むことでどういう命令かが具体的にわかる。

動的ビットの説明

前述の各命令の挙動を示すビットについて、以下引用。

データシートからの引用

NOTES:
AL = 8-bit accumulator
AX = 16-bit accumulator
CX = Count register
DS = Data segment
ES = Extra segment
Above/below refers to unsigned value
Greater = more positive;
Less = less positive (more negative) signed values
if d = 1 then ‘‘to’’ reg; if d e 0 then ‘‘from’’ reg
if w = 1 then word instruction; if w e 0 then byte instruction
if mod = 11 then r/m is treated as a REG field
if mod = 00 then DISP = 0*, disp-low and disp-high are absent
if mod = 01 then DISP = disp-low sign-extended to 16 bits, disp-high is absent
if mod = 10 then DISP = disp-high; disp-low
if r/m = 000 then EA = (BX) + (SI) + DISP
if r/m = 001 then EA = (BX) + (DI) + DISP
if r/m = 010 then EA = (BP) + (SI) + DISP
if r/m = 011 then EA = (BP) + (DI) + DISP
if r/m = 100 then EA = (SI) + DISP
if r/m = 101 then EA = (DI) + DISP
if r/m = 110 then EA = (BP) + DISP*
if r/m = 111 then EA = (BX) + DISP
DISP follows 2nd byte of instruction (before data if required)
*except if mod = 00 and r/m = 110 then EA = disp-high; disp-low.

if s w = 01 then 16 bits of immediate data form the operand
if s w = 11 then an immediate data byte is sign extended to form the 16-bit operand
if v e = then "count" = 1; if v = 1 then "count" in (CL) x = don’t care
z is used for string primitives for comparison with ZF FLAG

略語

各要素は基本的に略語で書かれてるので、最初ちょっと途惑った。ということで、それらの説明。

略語 元の語 用法
d direction(多分) レジスタへの操作か、レジスタからの操作かを示す
w word データがword長か否かを示す
mod mode 同命令内にあるdata部の扱いや、r/mの挙動を決める
DISP displacement メモリの位置指定などに使用
r/m register/memory(多分) レジスタを使ってのメモリ指定パターン

いくつか実例

MOV命令を読む際に使ったいくつかについて、実例を見てみる。

例1
16進数:b80100
 2進数:10111000 00000001 00000000

の場合。先頭ビットから見ていくと、一致する命令は"Immediate to Register"であることがわかる。以降のビットを命令表のこの命令と照らし合わせてみると

w 1
reg 000
data 000000001 00000000

であることがわかる。regはレジスタを示すビット列で、これについてもデータシートの最終ページに対応表があるのでそちらを参照すると、wが1の場合、000はレジスタAXを示す。以上よりこの命令は

mov ax, 0x0001

となることがわかる。

例2
16進数:c7070200
 2進数:11000111 00000111 00000010 00000000

の場合。同様に先頭ビットから見ていくと、一致する命令は"Immediate to Register/Memory"であることがわかる。以降のビットを命令表と照合してみると

w 1
mod 00
r/m 111
data 00000010 00000000

であることがわかる。r/m=111の場合、"EA = (BP) + DISP"が当てはまる。また、mod=00の場合、DISPは0であるとして扱われるので、DISPを示す要素は存在しない。つまり"EA = (BP)"となり、dataはコピーされる即値に相当する。以上より

mov [bp], 0x0002

となることがわかる

例3

16進数:c78718010200
 2真数:11000111 10000111 00011000 00000001 00000010 00000000

の場合。同様にしていくと、これもまた"Immediate to Register/Memory"である。命令決定以降のビットを照合していくと

w 1
mod 10
r/m 111
data 00000010 00000000

w=1より、dataは末尾16ビットが相当するのだが、ここで丁度真ん中の16ビットが謎の存在になる。mod=01を見ると、"if mod = 10 then DISP = disp-high; disp-low"とあり、このDISPが9~32ビット目までに相当している。なぜここに差し込まれるかというと、"DISP follows 2nd byte of instruction (before data if required)"という説明にあるように、dataがあるならその前に入るようになっている。あとはr/m=111より"EA = (BX) + DISP"であることがわかる。以上より

mov [bx+0x118], 0x0002

となる

例4

16進数:c70600010a000
 2進数:11000111 00000110 00000000 00000001 00001010 00000000

の場合、相変わらずこれも"Immediate to Register/Memory"である。以下同様にしていくと

w 1
mod 00
r/m 110
data 00001010 00000000

例3と同様にしてdataは表の通りとわかる。mod=00なので"if mod = 00 then DISP = 0*, disp-low and disp-high are absent"に相当するかと思いきや、このアスタリスクが曲者。"*except if mod = 00 and r/m = 110 then EA = disp-high; disp-low."なんていう説明がありまして、mod=00かつr/m=110の場合は即値のコピー先が"EA = (BP) + DISP"から"EA = disp-high; disp-low"に変更となる。つまり、即値をDISPで指定されるメモリの位置にコピーしろという命令になる。よって以上より

mov [0x100], 0x000a

となる。

最後に

この8086のデータシートは"8086 datasheet"なんてググれば出てきますが、これって"mnemonic © intel, 1978"って、今更誰が使うんだレベルの古さですね。なんという誰得エントリ。