INT 12h
int 12hを実行するとメモリの大きさがAXレジスタへ保存されます。
まず初めに動作を確認します。
8086実機及びQEMUで実行するとAXに027Fが格納されました。
これによりメモリの長さは639KBと分かります。
(本当は640KB搭載されているはずですが予約領域分1KBを引いたということでしょうか?)
ThinkPadでは0274(628KB)と少し小さくなりました。何故でしょうか。
nasm -f bin biostest.asm -o biostest.bin
[org 0x7C00]
bits 16
start:
cli ; 割り込み禁止
; セグメント初期化
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x7C00
sti
; 画面クリア (BIOS)
mov ax, 0x0003
int 0x10
; int 12h でメモリサイズを取得(AX = KB単位の基本メモリ)
int 0x12
; AXの値を16進数で画面に表示
call print_hex_word
.halt:
hlt
jmp .halt
; AXの値を16進数で表示する関数
print_hex_word:
push ax
push bx
push cx
mov dx, ax
mov cx, 4 ; 4桁の16進数
.next_digit:
rol dx, 4 ; 最上位4ビットを最下位に移動
mov bx, dx
and bx, 0x000F ; 下位4ビットを取得
mov bl, [hex_chars + bx] ; 対応するASCII文字を取得
; BIOS int 10h で文字を表示
mov ah, 0x0E ; テレタイプ出力
mov al, bl
int 0x10
loop .next_digit
pop cx
pop bx
pop ax
ret
hex_chars db '0123456789ABCDEF'
times 510-($-$$) db 0
dw 0xAA55
8086実機
sudo dd if=biostest.bin of=/dev/sdb bs=512 count=2 conv=notrunc
ThinkPad X280
qemu
qemu-system-i386 -fda biostest.bin
GITHUBのURL
今回読むソースは以下の位置にあります。
※先ほど動作確認で使用した実機に載っているBIOSとは違うものですが、細かい実装方法が違うだけで機能自体は同じはずです。
ソース
メモリの大きさをAXに格納しています。
起動(POST)時にMEMORY_SIZEに保存された値をAXへ格納するだけで、再検査は行っていません。
;--- INT 12 ----------------------------------------------------:
; MEMORY_SIZE_DETERMINE :
; THIS ROUTINE RETURNS THE AMOUNT OF MEMORY IN THE :
; SYSTEM AS DETERMINED BY THE POST ROUTINES. :
; NOTE THAT THE SYSTEM MAY NOT BE ABLE TO USE I/O MEMORY :
; UNLESS THERE IS A FULL COMPLEMENT OF 512K BYTES ON THE :
; PLANAR. :
; INPUT :
; NO REGISTERS :
; THE MEMORY_SIZE VARIABLE IS SET DURING POWER ON :
; DIAGNOSTICS ACCORDING TO THE FOLLOWING ASSUMPTIONS: :
; :
; 1. CONFIGURATION RECORD IN NON-VOLATILE MEMORY :
; EQUALS THE ACTUAL MEMORY SIZE INSTALLED. :
; :
; 2. ALL INSTALLED MEMORY IS FUNCTIONAL. IF THE :
; MEMORY TEST DURING POST INDICATES LESS, THEN THIS :
; VALUE BECOMES THE DEFAULT. IF NON-VOLATILE MEMORY :
; IS NOT VALID (NOT INITIALIZED OR BATTERY FAILURE) :
; THEN ACTUAL MEMORY DETERMINED BECOMES THE DEFAULT. :
; :
; 3. ALL MEMORY FROM 0 TO 640K MUST BE CONTIGUOUS. :
; :
; OUTPUT :
; (AX) = NUMBER OF CONTIGUOUS 1K BLOCKS OF MEMORY :
;---------------------------------------------------------------:
ASSUME CS:CODE,DS:DATA
MEMORY_SIZE_DETERMINE_1 PROC FAR
STI ; INTERRUPTS BACK ON
PUSH DS ; SAVE SEGMENT
CALL DDS ; ESTABLISH ADDRESSING
MOV AX,MEMORY_SIZE ; GET VALUE
POP DS ; RECOVER SEGMENT
IRET ; RETURN TO CALLER
MEMORY_SIZE_DETERMINE_1 ENDP
実際にメモリの長さを調べてMEMORY_SIZEへ格納しているところを探したのですが、32ビットモード用のコード等が多く複雑で見つけられませんでした。
検索に使ったコマンド
grep -i "INT 12" -n -R .
grep -i "MEMORY_SIZE_DETERMINE" -n -R .
最後に
いつか気力のある時に、MEMORY_SIZEへ大きさを代入しているところの処理を探し出して読んでみたいと思います。今回は2時間くらい探しても見つからなかったので心が折れました。
あと、MSI-16R4でint12hを実行してAXの中身を見ると大量の0が表示されました。
機種によって互換性がまちまちということでしょうか。
そもそもゲーム用のパソコンでこんな酔狂なことをする人はいないと思うのでこんな互換性は無くてもいいのかもしれませんが。。。




