How to make a new line and print the same characters in new line

*爱你&永不变心* 提交于 2019-12-02 08:04:02

When you write directly to video memory at B800:<adr>, the address of write decides what the value will be used for (depends on selected graphics(text!) mode of course).

In classic text mode 80x25 the video memory starts at B800:0000, and has size 80*25*2 bytes. 80*25 is probably self explanatory, 1 byte per character (in extended 8-bit ASCII encoding), so why *2? Each character has 1 more byte dedicated for colours. Actually they sit next to each other, so at B800:0000 is the ASCII value of character, and at B800:0001 is stored it's colour attribute.

Character+attribute pairs are stored from left to right row by row, so to write character '*' at position (40,12) (almost centre of screen), you have to write at address (y*160 + x*2) = (12*160 + 40*2) = 2000. The *160 is *80*2 = number of character+attribute pairs per row, ie. size of row in bytes:

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

Or you can shorten that to single WORD write as:

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

To print on next line you simply have to adjust the address either by +160 (to move under current character), or by adding the remaining size of row to the current address to get to the first char of next line, like +80 for the 2000 from example to move at the beginning of line 13 (14th line on screen).

See this page for further details about video memory layout:
http://www.shikadi.net/moddingwiki/B800_Text


BTW the more bytes you write at one time, the faster the code runs on real (original) HW, so in your case I would strongly prefer either the WORD write storing the ASCII+attribute pair together, or even DWORD writes (in 32b mode) storing two letters+two attributes with single instruction.

Your code does first write every second byte on even addresses setting the ASCII letters, then it does write every odd byte with colour value. I would do it in this way personally:

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
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!