I'm trying to learn assembly. I saw this example in printing "Hello World!(red text) with a backgound color(yellow)"
I managed to edit the code to just print spaces with yellow background by trial and error. However I cannot print a new line. if I add a new mov [200], ' '
for example (dont know if this is correct) it adds a character on a different line but a different color.. if I add 00010001b
after the comma if prints a different color which should blue.
can anyone give me a head start tutorial in this code. I just want to print another line for now.. Here is the working code so far.. it prints a whole line of yellow
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
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
来源:https://stackoverflow.com/questions/40016811/how-to-make-a-new-line-and-print-the-same-characters-in-new-line