0

組み立てを勉強しようと思っています。「Hello World!(red text) with a background color(yellow)」の印刷でこの例を見ました。

試行錯誤により、コードを編集して、背景が黄色のスペースだけを印刷することができました。ただし、改行を印刷できません。mov [200], ' 'たとえば、新しいものを追加すると(これが正しいかどうかわからない)、別の行に文字が追加されますが、色が異なります..00010001bカンマの後に追加すると、青色の別の色が印刷されます.

誰でもこのコードで有利なスタート チュートリアルを教えてもらえますか? 今のところ別の行を印刷したいだけです..これまでの作業コードは次のとおりです..黄色の行全体を印刷します

name "hi-world"


; hex    bin        color ;  ; 0      0000      black ; 1      0001    blue ; 2      0010      green ; 3      0011      cyan ; 4      0100    red ; 5      0101      magenta ; 6      0110      brown ; 7      0111  light gray ; 8      1000      dark gray ; 9      1001      light blue ; a      1010      light green ; b      1011      light cyan ; c      1100      light red ; d      1101      light magenta ; e      1110     yellow ; f      1111      white



org 100h

; set video mode     mov ax, 3     ; text mode 80x25, 16 colors, 8 pages (ah=0, al=3) int 10h       ; do it!

; cancel blinking and enable all 16 colors: mov ax, 1003h mov bx, 0 int 10h


; set segment register: mov     ax, 0b800h mov     ds, ax

; print "hello world" ; first byte is ascii code, second byte is color code.

mov [02h], ' '

mov [04h], ' '

mov [06h], ' '

mov [08h], ' '

mov [0ah], ' '

mov [0ch], ' '

mov [0eh], ' '   

mov [10h], ' '

mov [12h], ' '

mov [14h], ' '

mov [16h], ' '

mov [18h], ' '

mov [1ah], ' '

mov [1ch], ' '

mov [1eh], ' '   

mov [20h], ' '


; color all characters: mov cx, 34  ; number of characters. mov di, 03h ; start from byte after 'h'

c:  mov [di], 11101100b   ; light red(1100) on yellow(1110)
    add di, 2 ; skip over next ascii code in vga memory.
    loop c

; wait for any key press: mov ah, 0 int 16h

ret
4

1 に答える 1

2

でビデオ メモリに直接書き込む場合、書き込みB800:<adr>のアドレスによって、値が何に使用されるかが決まります (もちろん、選択したグラフィックス (テキスト!) モードによって異なります)。

クラシック テキスト モード 80x25 では、ビデオ メモリは から始まり、B800:0000サイズは 80*25*2 バイトです。80*25 はおそらく一目瞭然で、文字あたり 1 バイト (拡張 8 ビット ASCII エンコーディング) です。各文字には、色専用のさらに 1 バイトがあります。実際には隣同士にあるので、atB800:0000は文字の ASCII 値であり、atB800:0001は色属性として保存されます。

文字と属性のペアは、行ごとに左から右に格納されるため'*'、位置 (40,12) (画面のほぼ中央) に文字を書き込むには、アドレス (y*160 + x*2) = (12) に書き込む必要があります。 *160 + 40*2) = 2000. *160 は、*80*2 = 行ごとの文字 + 属性のペアの数です。行のサイズ (バイト単位):

mov   BYTE PTR [2000],'*'
mov   BYTE PTR [2001],2Eh  ; yellow ink, green paper

または、次のように単一の WORD 書き込みに短縮できます。

mov   WORD PTR [2000],2E00h + '*'

次の行に印刷するには、アドレスを +160 (現在の文字の下に移動するため) に調整するか、行の残りのサイズを現在のアドレスに追加して、次の行の最初の文字を取得する必要があります。 fromの2000例を 13 行目の先頭 (画面の 14 行目) に移動します。

ビデオ メモリ レイアウトの詳細については、このページを参照してください:
http://www.shikadi.net/moddingwiki/B800_Text


ところで、一度に書き込むバイト数が多いほど、実際の(元の)HWでコードが高速に実行されるため、ASCII +属性ペアを一緒に保存するWORD書き込み、またはDWORD書き込み(32bモード)のいずれかを強くお勧めします) 1 つの命令で 2 つの文字 + 2 つの属性を格納します。

あなたのコードは最初にASCII文字を設定する偶数アドレスに2バイトごとに書き込み、次に奇数バイトごとに色の値を書き込みます。個人的には次のようにします。

mov ax,0B800h
mov es,ax
mov di,<target_address = y*160 + x*2>  ; es:di set up
mov ah,<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,'H'  ; al = letter, ah = attribute (ax set up)
stosw       ; [es:di] = ax, di += 2
mov al,'e'  ; change only letter in ax
stosw
mov al,'l'
stosw
mov al,'l'
stosw
...

; the mov al,<char> can be replaced by LODSB
; reading ascii string from ds:si.
; then it would look like:
mov   si,<address_of_ascii_string>
lodsb
stosw
lodsb
stosw
... so many times as the string length
于 2016-10-13T10:14:40.123 に答える