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?

IBM PC BIOSを読み解く:INT 12h とメモリの大きさ取得の仕組み

Posted at

INT 12h

int 12hを実行するとメモリの大きさがAXレジスタへ保存されます。

まず初めに動作を確認します。

8086実機及びQEMUで実行するとAXに027Fが格納されました。
これによりメモリの長さは639KBと分かります。
(本当は640KB搭載されているはずですが予約領域​​分1KBを引いたということでしょうか?)
ThinkPadでは0274(628KB)と少し小さくなりました。何故でしょうか。

nasm -f bin biostest.asm -o biostest.bin
biostest.asm
[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

9eef9ba6be12f.jpg

ThinkPad X280

6d6289c3271128.jpg
0952a4e0ab641.jpg

qemu

qemu-system-i386 -fda biostest.bin

image.png

GITHUBのURL

今回読むソースは以下の位置にあります。
※先ほど動作確認で使用した実機に載っているBIOSとは違うものですが、細かい実装方法が違うだけで機能自体は同じはずです。

ソース

メモリの大きさをAXに格納しています。
起動(POST)時にMEMORY_SIZEに保存された値をAXへ格納するだけで、再検査は行っていません。

BIOS.ASM
;--- 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-16R4int12hを実行してAXの中身を見ると大量の0が表示されました。
機種によって互換性がまちまちということでしょうか。
そもそもゲーム用のパソコンでこんな酔狂なことをする人はいないと思うのでこんな互換性は無くてもいいのかもしれませんが。。。
ccaae8fd5c5638.jpg

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?