リアル モード アドレッシングについて、私が誤解している基本的なことがあるはずです。リアル モードで BIOS 割り込みを介してテキストを印刷する機能を設定しようとしています。DOSBox で実行される .com ファイルを使用してコードをテストしています。.text セクションは 0x1000 (.com ファイルでは 0x0F00) で終わります。それで、そのテキストの最初の文字を印刷したいとしましょう。
xor ebx, ebx
mov ecx, 1
mov ah, 10
mov al, ds:[0x1000]
int 0x10
私には想像力がないので、それは機能し、「H」を出力します。しかし、同じ文字を印刷したくありません。ポインターを渡したいのですが、さらにテキストを出力するときにそのポインターをインクリメントしたいと考えています。この段階では、レジスタからオフセットを読み取るだけで十分です。そこで、以下の変更を行います。
mov edx, 0x1000
mov al, ds:[edx]
そして、文字は印刷されません。esi および edi レジスタを使用してみましたが、同じ結果です。lea edx を使用すると、バイト ptr [0x1000] は同じ結果になります。さらに悪いことに、同等の 16 ビット (dx、si、di) を使用しようとすると、プログラムがハングアップします。.com ファイル内のマシン コードを調べてみましたが、明らかに間違っているものは見つかりませんでした。
カスタム リンカー スクリプトと objcopy 呼び出しを使用して gcc でコードをコンパイルし、.com ファイルを作成しています。ライブラリはリンクされておらず、ターゲット アーキテクチャは 386 です。
どんな助けでも大歓迎です。
編集:完全なリスト。
方向
.intel_syntax
.global _printChar
_printChar:
push ebp;
mov ebp, esp;
xor edx, edx;
xor ebx, ebx;
xor eax, eax;
mov ecx, 1;
mov ah, 10;
mov edx, 0x1000;
mov al, ds:[edx];
int 0x10;
mov esp, ebp
pop ebp;
ret;
dirTest.c
asm
(
".code16gcc;\n" \
"call _dosmain;\n" \
"mov ah, 0x4C;\n" \
"int 0x21;\n"
);
#include "directio.h"
int dosmain(void)
{
printChar("Hello World!");
return 0;
}
com_mingw.ld
SECTIONS
{
. = 0x0100;
.text :
{
*(.text);
}
.data :
{
*(.data);
*(.bss);
*(.rodata);
}
_heap = ALIGN(4);
}
これらはすべて、次のコマンド ラインでコンパイルされます。
gcc -std=gnu99 -Os -nostdlib -m32 -masm=intel -march=i386 -ffreestanding -o dirTest.com -Wl,--nmagic,--script=com_mingw.ld dirTest.c directio.s
に続く
objcopy dirTest.com -O binary