「手探りでCUI OS作成に挑む」連載
この記事は「手探りでCUI OS作成に挑む」連載の一部です。
全体の目次は「手探りでCUI OS作成に挑む」連載目次を御覧下さい。
なぜレジスタを退避する必要があるのか?
関数を呼び出すと、呼び出し元(caller)と呼び出された関数(callee)が同じレジスタを使う。
レジスタの値を上書きしてしまうと、呼び出し元に戻ったときにデータが壊れてしまう。
; 呼び出し元
mov ax, 0x1234
call my_func
; ここで ax を使いたい → でも関数が ax を書き換えていたら値が消える
PUSHA / POPAの検証コード
boot.asm
org 0x7C00
start:
; レジスタに値を入れる
mov ax, 'A'
mov bx, 'B'
mov cx, 'C'
mov dx, 'D'
call print_regs ; レジスタの値を画面出力(A B C D)
; レジスタの値保存(pusha)
pusha
; レジスタの値を変更(X)
mov ax, 'X'
mov bx, 'X'
mov cx, 'X'
mov dx, 'X'
call print_regs ; 変更後の値を画面出力(X X X X)
; レジスタの値復元(popa)
popa
call print_regs ; A B C Dに戻っている
jmp $ ; CPU停止
;-------------------------------
print_regs:
; AX 低 8 ビット(al)
mov ah, 0x0E
mov al, ah ; ax='A'(0x0041),ah=0x00,al=0x41('A')
int 0x10
; 空白出力
mov al, ' '
int 0x10
; BX 低 8 ビット(bl)
mov al, bl ; bx='B'(0x0042),bl=0x42('B')
int 0x10
mov al, ' '
int 0x10
; CX 低 8 ビット(cl)
mov al, cl ; cx='C'(0x0043),cl=0x43('C')
int 0x10
mov al, ' '
int 0x10
; DX 的低 8 ビット(dl)
mov al, dl ; dx='D'(0x0044),dl=0x44('D')
int 0x10
; 改行
mov al, 13
int 0x10
mov al, 10
int 0x10
ret
;-------------------------------
times 510-($-$$) db 0
dw 0xAA55
動作結果
ubuntu@ubuntu:~/kaihatsu/test2$ nasm -f bin boot.asm -o boot.bin
ubuntu@ubuntu:~/kaihatsu/test2$ qemu-system-i386 -fda boot.bin