0

我正在努力学习组装。我在用背景颜色(黄色)打印“Hello World!(红色文本)”时看到了这个例子

通过反复试验,我设法编辑代码以仅打印具有黄色背景的空间。但是我无法打印新行。例如,如果我添加一个新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 编码中),那么为什么是 *2?每个字符还有 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(移动到当前字符下),或者将行的剩余大小添加到当前地址以获取下一行的第一个字符,例如 +80 from 示例移动到第200013 行(屏幕上的第 14 行)的开头。

有关显存布局的更多详细信息,请参阅此页面:http:
//www.shikadi.net/moddingwiki/B800_Text


顺便说一句,您一次写入的字节越多,代码在真实(原始)硬件上运行的速度越快,因此在您的情况下,我强烈希望将 ASCII + 属性对存储在一起的 WORD 写入,甚至是 DWORD 写入(在 32b 模式下) ) 用单个指令存储两个字母+两个属性。

您的代码确实首先在设置 ASCII 字母的偶数地址上每隔一个字节写入一个字节,然后它会在每个奇数字节中写入颜色值。我个人会这样做:

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 回答