0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

z80アセンブラで生成した機械語をV30実機上で実行

0
Last updated at Posted at 2026-09-19

目的

NECのV30CPU上にて、z80を用いて生成した機械語を実行する環境を整えます。
ゲームボーイの仕様を研究しており、z80のニーモニックの方が慣れているのでz80用のアセンブラを使用します。
※z80から追加された命令は使わないよう注意します。
ゲームボーイ研究日記
8080とz80で機械語を比較

説明

NECが製造していた8086互換CPUは8080CPUの命令を実行する互換モードがあります。
V30上でいつでもV30の8086以下のように実装しました。

配置

test.binの配置 | メモリ上の配置 | 説明
0x0000 | 0x7C00 | BIOSから読み込まれる8086のブートローダ
0x0E00 | 0x7E00 | 8080コードを呼ぶ為の8086コード
0x1000 | 0x8000 | 8080コード(今回の対象)

BIOSがブートローダを読み込む原理に関しては前に以下の記事で検証しています。
ブートローダのORG0x7C00とは何か?BIOSを改造して実験

手順

ブートローダ

  1. ブートローダから2セクタを読み込む(ブートローダ自体はBIOSから読み込まれている)

8086コード
2. IVT 0x80に8080コードの開始アドレス(0x8000)を登録する
3. V30のCPUが8080モードへ遷移する機械語0x0F, 0xFFを実行する
6. 8080側でVRAMに見立てた0x6000のデータをVGAのVRAM領域0xB800へ複製して画面表示する

8080コード
4. VRAMバッファ[0x6000]へ値を入れる
5. V30のCPUが8086モードへ復帰する機械語0xED,0xFDを実行する

実行結果

8080のコードで1から10の合計を計算し、その結果を8086モードで画面上に描画されている。
3708c2f36f261

コード

nasm -f bin 8086.asm -o 8086.bin
z80asm -o 8080.bin 8080.asm
cat 8086.bin 8080.bin > test.bin
lsblk
sudo dd if=test.bin of=/dev/sdb bs=512 count=3 conv=notrunc
8086.asm
org 0x7C00

start:
    xor ax, ax
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov sp, 0x7C00

    ; ディスクから第2(8086モード作業場),3(8080側)セクタを 0x7E00 に読み込む
    mov ah, 0x02        ; INT 13h 2: 読み込み
    mov al, 2           ; 読み込むセクタ数 = 1
    mov ch, 0           ; シリンダ = 0
    mov cl, 2           ; セクタ番号 = 2(1始まり)
    mov dh, 0           ; ヘッド = 0
    mov dl, 0x80        ; ドライブ番号
    mov bx, 0x7E00      ; 読み込み先アドレス
    int 0x13
    jc disk_error       ; エラー時に無限ループ

    ; 読み込んだコードへ跳ぶ(第2セクタ)
    jmp 0x0000:0x7E00

disk_error:
    jmp $

times 510-($-$$) db 0
dw 0xAA55


%define TARGET_VECC 0x80
%define TARGET_ADDR (TARGET_VECC * 4)

BUFFER_ADDR equ 0x6000  ; 8080モード用の文字バッファ

start2:
    cli
    xor ax, ax
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov sp, 0x7C00

    ; --- IVT 0x80 に 8080コードの開始地点を登録 ---
    mov word [TARGET_ADDR], 0x8000 ; オフセット
    mov word [TARGET_ADDR + 2], 0           ; セグメント(CS)
    
    call init_8080buffer

    mov si, msg_enter;;;;
    call print_string

    ; 8080モードへ移行
    db 0x0F, 0xFF, TARGET_VECC 
    

; 8086復帰
after_8080:
    xor ax, ax
    mov ds, ax
    mov ax, 0xB800
    mov es, ax
    
    ; --- バッファからVRAMに複製 ---
    call copy_8080buffer_to_vram
    
    ;mov si, msg_back
    ;call print_string
    
hlt_loop:
    hlt
    jmp hlt_loop

    
;-----------------------
; 8080用画面バッファからVRAMへ複製
;-----------------------
copy_8080buffer_to_vram:
    push ax
    push cx
    push si
    push di
    push ds
    push es

    xor ax, ax
    mov ds, ax
    mov si, BUFFER_ADDR

    mov ax, 0B800h
    mov es, ax
    xor di, di

    mov cx, 4000          ; 80*25*2
    rep movsb ; DS:SI → ES:DI

    pop es
    pop ds
    pop di
    pop si
    pop cx
    pop ax
    ret
    
;-----------------------
; 8080画面出力用BUFFER初期化
;-----------------------
init_8080buffer:
    push ax
    push cx
    push es
    push di

    ; ES=0x0000 DI=0x6000
    xor ax, ax
    mov es, ax
    mov di, BUFFER_ADDR

    mov cx, 80*25
    mov ax, 0x0720    ; AH=属性, AL=' '
    cld
    rep stosw ; ES:[DI] ← AX , DI ← DI + 2

    pop di
    pop es
    pop cx
    pop ax
    ret

;-----------------------
; 文字列出力
;-----------------------
print_string:
    lodsb
    or al, al
    jz .done
    mov ah, 0x0E
    int 0x10
    jmp print_string
.done:
    ret

msg_enter db "Entering 8080 mode...", 13, 10, 0
msg_back  db "Successfully returned!", 13, 10, 0

times 512-($-start2) db 0
8080.asm
org 0x8000

ld a, 0
ld b, 10   ; 10回ループ

sum_loop:
    add a, b
    dec b
    jp nz, sum_loop

    ; ここでAに合計が入っている (55)
    ; ASCII 55=7 よって7が表示される
    
ld (0x6000), a
ld a, 0x4f
ld (0x6001), a

db 0xed,0xfd
ds 512 - ($ - 0x8000)
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?