ビデオ メモリ (@ 0xb8000で始まる) に書き込む場合、画面上のすべてのセルに対して 2 バイトがあります。表示する文字は 1 バイト目にあり、属性は 2 バイト目にあります。赤 (カラー コード 0x40) スペース (0x20) 文字を画面の最初のセルに出力するには、次のようにバイトをメモリに配置する必要があります。
0xb800:0x0000 : 0x20 ; ASCII char for 0x20 is ' '
0xb800:0x0001 : 0x40 ; Red background, black foreground
あなたのコードでは、次のようなコードでこれを行おうとしていたようです:
mov al,0x40 ;colour
mov ah,' ' ;character
.red:
cmp bx,0x0FA0
je .end
mov WORD [es:bx], ax
inc bx
jmp .red
残念ながら、x86 アーキテクチャはリトルエンディアンであるため、メモリに配置される値は最下位バイトが最初で最上位バイトが最後になります (16 ビットのWORDを処理する場合)。0x2040を含むAXがあり、 WORD全体をビデオ メモリに移動しました。たとえば、次のバイトが最初のセルに書き込まれます。mov WORD [es:bx], ax
0xb800:0x0000 : 0x40 ; ASCII char for 0x40 is `@'
0xb800:0x0001 : 0x20 ; Green background, black foreground
これは緑@
だと思いますが、2 番目のバグのため、赤く見える可能性があります。これを修正するには、 AXレジスタの文字と属性の位置を逆にする必要があります( AHとALの値を交換します)。コードは次のようになります。
mov ah,0x40 ;colour is now in AH, not AL
mov al,' ' ;character is now in AL, not AH
.red:
cmp bx,0x0FA0
je .end
mov WORD [es:bx], ax
inc bx
jmp .red
2 番目のバグは、ビデオ領域のトラバースに関連しています。各セルは 2 バイトを使用するため、反復ごとにBXカウンターを 2ずつインクリメントする必要があります。あなたのコードは:
mov WORD [es:bx], ax
inc bx ; Only increments 1 byte where it should be 2
jmp .red
BXに 2 を追加するようにコードを変更します。
mov WORD [es:bx], ax
add bx,2 ; Increment 2 since each cell is char/attribute pair
jmp .red
AXの値を取り、それをES:[DI]にコピーするSTOSW命令を使用して、コードを単純化できます。この命令の前にREPを付けると、 CX回繰り返されます (反復ごとにそれに応じて DI が更新されます)。コードは次のようになります。
error:
mov ax,0xb800
mov es,ax ;Set video segment to 0xb800
mov ax,0x4020 ;colour + space character(0x20)
mov cx,2000 ;Number of cells to update 80*25=2000
xor di,di ;Video offset starts at 0 (upper left of screen)
rep stosw ;Store AX to CX # of words starting at ES:[DI]
コードは、コードの先頭でCLDを使用して方向フラグを既にクリアしているため、反復ごとにREPによってDIが増加します。方向フラグがSTDで設定されていた場合、DIはデクリメントされます。