読者です 読者をやめる 読者になる 読者になる

【お知らせ】プログラミング記事の投稿はQiitaに移行しました。

8086版V6のa.out

x86-16 UNIX V6

8086版V6のa.outはマジックナンバーで識別することにしました。PDP-11のマジックナンバーはブランチ命令に由来します。

0407(0x107) br 020(0x10) .textと.dataは同じセグメントで連続
0410(0x108) br 022(0x12) .textと.dataは別セグメントに分離
0411(0x109) br 024(0x14) .textと.dataは別メモリ空間に分離

8086で相当する命令をマジックナンバーとしました。

0xeb 0x0e jmp short 0x10
0xeb 0x10 jmp short 0x12
0xeb 0x12 jmp short 0x14

ちなみにV7/x86は32bit化されているため、V7(V6と同じ)のヘッダの各項目を単純に32bit化したフォーマットで、マジックナンバーPDP-11と同じです。

cv

ACKではUNIX V7(PDP-11)がサポートされています。具体的にはリンク後にcvコマンドによりバイナリフォーマットを変換します。cvコマンドに手を入れて、上で決めたマジックナンバーを出力するように改造しました。

nm, strip

マジックナンバーをいじったことでV6のnmやstripが使えなくなりましたが、マジックナンバーを変えるだけで簡単に対応できます。

使用例

ACKで8086版V6のバイナリを出力して、改造したツールで処理してみます。

write.s
mov ax, #1
int 7
.data1 4
.data2 hello, 6

mov ax, #0
int 7
.data1 1

.sect .data
hello: .ascii "hello\n"
$ m2cc -c write.s
$ m2ld write.o -o write.ack
$ 8086v6-cv write.ack write
$ v6nm write
000000t
000020d
000020d
000026b
000020d hello
$ v6strip write
$ file write
write: DOS executable (COM)
$ od -tx1z -Ax write
000000 eb 0e 10 00 06 00 00 00 00 00 00 00 00 00 01 00  >................<
000010 b8 01 00 cd 07 04 10 00 06 00 b8 00 00 cd 07 01  >................<
000020 68 65 6c 6c 6f 0a                                >hello.<
000026
$ 7run write
hello
$ 7run -d write
0000: b80100        mov ax, 0001
0003: cd07          int 7
0005: 04            ; sys write
0006: 1000          ; arg
0008: 0600          ; arg
000a: b80000        mov ax, 0000
000d: cd07          int 7
000f: 01            ; sys exit

※ v6nmで表示されている名前のないシンボルは、セクションの始まりを示しているようです。

libc

現時点ではアセンブラしか使えません。C言語を使うにはlibcを整備する必要があります。V6付属のコンパイラを移植する予定のため、ACKの整備はそれほど重視していません。ですがコンパイラの移植に失敗した時の担保として、ある程度はACKも整備しておきたいと思います。

※ V7/x86は32bitのためACKやlibcを流用できません。

libcはアセンブラで書かれています。手動で変換するとアセンブラを変えた時に文法の対応が必要となり二度手間です。アセンブリを変換するトランスレータを作って、出力文法を切り替えられるようにすることが望ましいです。

そのためV6移植ハッカソンではトランスレータから着手する計画です。