Assembly 为什么不是';使用0Eh 10h中断时,文本是否有颜色?
我使用10h中断,将AH作为0Eh输出“Hello World!”文本已输出,但未着色。我正在qemu-system-x86_64上运行它,并使用NASM进行组装,我的代码如下:Assembly 为什么不是';使用0Eh 10h中断时,文本是否有颜色?,assembly,x86,nasm,x86-64,qemu,Assembly,X86,Nasm,X86 64,Qemu,我使用10h中断,将AH作为0Eh输出“Hello World!”文本已输出,但未着色。我正在qemu-system-x86_64上运行它,并使用NASM进行组装,我的代码如下: BITS 16 start: mov ax, 07C0h ; Set up 4K stack space after this bootloader add ax, 288 ; (4096 + 512) / 16 bytes per paragraph
BITS 16
start:
mov ax, 07C0h ; Set up 4K stack space after this bootloader
add ax, 288 ; (4096 + 512) / 16 bytes per paragraph
mov ss, ax
mov sp, 4096
mov ax, 07C0h ; Set data segment to where we're loaded
mov ds, ax
mov si, text_string ; Put string position into SI
call print_string ; Call our string-printing routine
jmp $ ; Jump here - infinite loop!
text_string db 'Hello World!', 0
print_string: ; Routine: output string in SI to screen
mov ah, 0Eh ; int 10h 'print char' function
mov bh, 0x00
mov bl, 0x03
.repeat:
lodsb ; Get character from string
cmp al, 0
je .done ; If char is zero, end of string
int 10h ; Otherwise, print it
jmp .repeat
.done:
ret
times 510-($-$$) db 0 ; Pad remainder of boot sector with 0s
dw 0xAA55 ; The standard PC boot signature
我可以用09代替0E,在10小时中断时使用彩色打印。但是,要使用此方法,必须更改每个字符后的光标位置。这是工作代码
BITS 16
start:
mov ax, 07C0h ; Set up 4K stack space after this bootloader
add ax, 288 ; (4096 + 512) / 16 bytes per paragraph
mov ss, ax
mov sp, 4096
mov ax, 07C0h ; Set data segment to where we're loaded
mov ds, ax
mov si, text_string ; Put string position into SI
call print_string ; Call our string-printing routine
jmp $ ; Jump here - infinite loop!
text_string db 'Hello World!', 0
print_string: ; Routine: output string in SI to screen
.repeat:
mov ah, 09h ; int 10h 'print char' function
mov bh, 0x00
mov bl, 0x03
mov cx, 01h
lodsb ; Get character from string
cmp al, 0
je .done ; If char is zero, end of string
int 10h ; Otherwise, print it
mov bh, 00h
mov ah, 03h
int 10h
mov ah, 02h
mov bh, 00h
inc dl
int 10h
jmp .repeat
.done:
ret
times 510-($-$$) db 0 ; Pad remainder of boot sector with 0s
dw 0xAA55 ; The standard PC boot signature
我可以用09代替0E,在10小时中断时使用彩色打印。但是,要使用此方法,必须更改每个字符后的光标位置。这是工作代码
BITS 16
start:
mov ax, 07C0h ; Set up 4K stack space after this bootloader
add ax, 288 ; (4096 + 512) / 16 bytes per paragraph
mov ss, ax
mov sp, 4096
mov ax, 07C0h ; Set data segment to where we're loaded
mov ds, ax
mov si, text_string ; Put string position into SI
call print_string ; Call our string-printing routine
jmp $ ; Jump here - infinite loop!
text_string db 'Hello World!', 0
print_string: ; Routine: output string in SI to screen
.repeat:
mov ah, 09h ; int 10h 'print char' function
mov bh, 0x00
mov bl, 0x03
mov cx, 01h
lodsb ; Get character from string
cmp al, 0
je .done ; If char is zero, end of string
int 10h ; Otherwise, print it
mov bh, 00h
mov ah, 03h
int 10h
mov ah, 02h
mov bh, 00h
inc dl
int 10h
jmp .repeat
.done:
ret
times 510-($-$$) db 0 ; Pad remainder of boot sector with 0s
dw 0xAA55 ; The standard PC boot signature
要更改光标位置,请执行以下操作:
text_string db 'Hello World!', 0
text_len = ($-text_string)-1
mov ah,3
xor bh,bh
int 10h
add dh,text_len
cmp dh,79
jb short P1
sub dh,79
inc dl
P1: mov ah,2
int 10h
RBIL->inter61a.zip->INTERRUP.A
--------V-1002-------------------------------
INT 10 - VIDEO - SET CURSOR POSITION
AH = 02h
BH = page number
0-3 in modes 2&3
0-7 in modes 0&1
0 in graphics modes
DH = row (00h is top)
DL = column (00h is left)
Return: nothing
SeeAlso: AH=03h,AH=05h,INT 60/DI=030Bh,MEM 0040h:0050h
--------V-1003-------------------------------
INT 10 - VIDEO - GET CURSOR POSITION AND SIZE
AH = 03h
BH = page number
0-3 in modes 2&3
0-7 in modes 0&1
0 in graphics modes
Return: AX = 0000h (Phoenix BIOS)
CH = start scan line
CL = end scan line
DH = row (00h is top)
DL = column (00h is left)
Notes: a separate cursor is maintained for each of up to 8 display pages
many ROM BIOSes incorrectly return the default size for a color display
(start 06h, end 07h) when a monochrome display is attached
With PhysTechSoft's PTS ROM-DOS the BH value is ignored on entry.
SeeAlso: AH=01h,AH=02h,AH=12h/BL=34h,MEM 0040h:0050h,MEM 0040h:0060h
我更喜欢直接写入0B800h的地址
mov ah,3 ; calculating the target offset address from the cursor position
xor bh,bh
int 10h
xor cx,cx
add dl,dl ; column
mov cl,dl
xor ax,ax
mov al,dh ; row
mov bx,160
mul bx
add ax,cx
mov di,ax
mov ax,0B800h
mov es,ax
mov si,text_string
mov cx,text_len
mov ah,3 ; color
cld
RP: lodsb ; get byte from DS:SI
stosw ; store word in ES:DI
loop RP
未测试,但我希望没有出现错误。要更改光标位置:
text_string db 'Hello World!', 0
text_len = ($-text_string)-1
mov ah,3
xor bh,bh
int 10h
add dh,text_len
cmp dh,79
jb short P1
sub dh,79
inc dl
P1: mov ah,2
int 10h
RBIL->inter61a.zip->INTERRUP.A
--------V-1002-------------------------------
INT 10 - VIDEO - SET CURSOR POSITION
AH = 02h
BH = page number
0-3 in modes 2&3
0-7 in modes 0&1
0 in graphics modes
DH = row (00h is top)
DL = column (00h is left)
Return: nothing
SeeAlso: AH=03h,AH=05h,INT 60/DI=030Bh,MEM 0040h:0050h
--------V-1003-------------------------------
INT 10 - VIDEO - GET CURSOR POSITION AND SIZE
AH = 03h
BH = page number
0-3 in modes 2&3
0-7 in modes 0&1
0 in graphics modes
Return: AX = 0000h (Phoenix BIOS)
CH = start scan line
CL = end scan line
DH = row (00h is top)
DL = column (00h is left)
Notes: a separate cursor is maintained for each of up to 8 display pages
many ROM BIOSes incorrectly return the default size for a color display
(start 06h, end 07h) when a monochrome display is attached
With PhysTechSoft's PTS ROM-DOS the BH value is ignored on entry.
SeeAlso: AH=01h,AH=02h,AH=12h/BL=34h,MEM 0040h:0050h,MEM 0040h:0060h
我更喜欢直接写入0B800h的地址
mov ah,3 ; calculating the target offset address from the cursor position
xor bh,bh
int 10h
xor cx,cx
add dl,dl ; column
mov cl,dl
xor ax,ax
mov al,dh ; row
mov bx,160
mul bx
add ax,cx
mov di,ax
mov ax,0B800h
mov es,ax
mov si,text_string
mov cx,text_len
mov ah,3 ; color
cld
RP: lodsb ; get byte from DS:SI
stosw ; store word in ES:DI
loop RP
未测试,但我希望没有错误。我认为比标记为已接受的更好的方法是使用中断10h的函数13h。此函数用于将整个字符串以及属性(颜色)发送到屏幕。此功能有四种操作模式,在
AL
寄存器中指定
AL=00h:为BL
中的属性分配所有字符;不要更新光标位置。AL=01h:为
BL
中的属性分配所有字符;更新光标位置。AL=02h:使用字符串中的属性;不要更新光标位置。
AL=03h:使用字符串中的属性;更新光标位置 因此,您可以通过在模式
00h
或01h
的BL
中指定属性,为整个字符串使用相同的属性(颜色),或者将属性混合在字符串本身中,以使用不同的属性打印每个字符
我看到这种方法的唯一缺点是,您必须预先知道字符串的长度(将其放入CX
),因为此函数不能处理以null结尾的字符串。但是,另一方面,将字符串的一个字节长度存储在其字符之前,而不是在其字符之后存储空字符,可能有一些好处:不需要遍历整个字符串就可以知道其长度;一个字节的长度不会比空终止符占据更多的位置。即使是两个字节的长度也不是很大的浪费。您可以将两字节的长度直接加载到
CX
中。您也可以对单字节长度执行同样的操作,但请确保在之后清除CH
单独使用字符串的每个字符的ability属性有时也很有用
其他寄存器与往常一样:BH
是页码。DX
是屏幕上字符串的起始位置:DH:DL=Y:X
ES:BP
指向内存中字符串的第一个字符
如果使用电传打字机模式(01h
或03h
),ASCII控制字符将正确解释,而不是打印为符号。它们还将光标位置更新到字符串的末尾
要使其连续工作,可以使用函数AH=03h
获取光标位置。这样做是为了将光标位置加载到DH:DL
,以便在随后调用AH=13h
时直接使用它从该位置打印字符串。我是这样做的:
# Get cursor position.
getcur: mov $0x03, %ah # Get cursor position into DH:DL = Y:X.
int $0x10 # Video BIOS interrupt.
ret # Return to the caller.
# Print string with attributes.
# `putsa` expects attributes in `BL`.
# `puts` uses the default attributes (silver on black).
# Both expect a pointer to the string in `ES:SI`.
# The string should start with a 2-byte length information.
puts: mov $0x07, %bl # Default attribute: silver on black.
putsa: call getcur # Get cursor position into DH:DL.
mov (%si), %cx # Length of the string into `CX`.
mov %si, %bp # Prepare the pointer:
add $2, %bp # Skip the 2-byte length word.
mov $0, %bh # Use page #0.
mov $0x1301, %ax # Print string and update cursor.
int $0x10 # Video BIOS interrupt.
ret # Return to the caller.
调用(假设ES
设置正确):
数据部分:
msgHello: .word 13 # Length of the string.
.ascii "Hello, World!" # The string itself.
哦,服务仅适用于1986年1月19日及以后的XTs、ATs、EGAs和PC敞篷车。但我想这不会带来任何问题,除非你正在处理一件严重的旧垃圾-J我认为比标记为接受的更好的方法是使用中断10h的函数13h。此函数用于将整个字符串以及属性(颜色)发送到屏幕。此功能有四种操作模式,在
AL
寄存器中指定
;make to use mov ah,0eh
bits 16
org 0x7c00
jmp basla
; clear screen with colour you want
basla:
;pencere boyutu 80x25 karakter
mov ah,06h
mov al,00h
mov bh,0ach ; ah zemin rengi,ch karakter rengi
mov cx,00h ;silmeye pencerenin sol ustunden basla
mov dx,184fh ;18h(24.satir) ve 4fh(79.sutun)a kadar sil.
int 10h
;then print your program
mov di,isim ;dizinin ilk adresini di kutuk yazmacina ata
call yazbas ; alt program cagriliyor
mov di,isim2 ;ikinci dizinin adresi ataniyor
call yazbas ;ayni alt program cagriliyor
jmp $ ;sonsuz dongu
yazbas:
mov ah,0eh
mov al,[di]
int 10h
inc di
or al,al
jz bitti
jmp yazbas
bitti:
ret
isim db "attila oguz",0
isim2 db "isletim duzenegine giris",0
times 510-($-$$) db 0
dw 0xaa55
AL=00h:为BL
中的属性分配所有字符;不要更新光标位置。AL=01h:为
BL
中的属性分配所有字符;更新光标位置。AL=02h:使用字符串中的属性;不要更新光标位置。
AL=03h:使用字符串中的属性;更新光标位置 因此,您可以通过在模式
00h
或01h
的BL
中指定属性,为整个字符串使用相同的属性(颜色),或者将属性混合在字符串本身中,以使用不同的属性打印每个字符
我看到这种方法的唯一缺点是,您必须预先知道字符串的长度(将其放入CX
),因为此函数不能处理以null结尾的字符串。但是,另一方面,将字符串的一个字节长度存储在其字符之前,而不是在其字符之后存储空字符,可能有一些好处:不需要遍历整个字符串就可以知道其长度;一个字节的长度不会比空终止符占据更多的位置。即使是两个字节的长度也不是很大的浪费。您可以将两字节的长度直接加载到
CX
中。您也可以对单字节长度执行同样的操作,但请确保在之后清除CH
单独使用字符串的每个字符的ability属性有时也很有用
其他寄存器与往常一样:BH
是页码。DX
是启动