我正在使用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
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
答案 0 :(得分:2)
我可以使用09进行10h中断而不是0E打印颜色。但是,您必须在每个字符后更改光标位置才能使用此方法。这是工作代码。
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
答案 1 :(得分:1)
我认为比标记为接受的更好的想法是使用中断10h的功能13h。该函数应该将整个字符串与属性(颜色)一起发送到屏幕。此功能有四种操作模式,在AL
寄存器中指定。
AL = 00h:为
BL
中的所有字符分配属性;不要更新光标位置 AL = 01h:为BL
中的所有字符分配属性;更新光标位置 AL = 02h:在字符串中使用属性;不要更新光标位置 AL = 03h:在字符串中使用属性;更新光标位置。
因此,您可以通过在BL
中为模式00h
或01h
指定属性,为整个字符串使用相同的属性(颜色),或者将字符串中的属性混合在一起打印具有不同属性的每个字符。
我用这种方法看到的唯一缺点就是你必须先知道字符串的长度(把它放到CX
中),因为这个函数不能用以空字符结尾的字符串。
但是,另一方面,在字符之前存储字符串的一个字节长度而不是字符之后的空字符可能有一些好处:您不需要遍历整个字符串以了解其长度;并且一个字节的长度不会占用空终止符。即使是两个字节的长度也不是浪费。您可以将两个字节的长度直接加载到CX
。您也可以使用一个字节长度执行相同的操作,但请确保之后清除CH
。
单独使用能力属性字符串的每个字符也可能有用。
其他寄存器与往常一样:
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
已正确设置):
# Print a string with attributes.
lea msgHello, %si # String to print (after 2-byte length)
mov $0x0C, %bl # Attributes: light red on black.
call putsa
# Print it one more time with different attributes.
# Note we don't have to set the pointer: it's already set.
mov $0x0C, %bl # Attributes: yellow on black.
call putsa
数据部分:
msgHello: .word 13 # Length of the string.
.ascii "Hello, World!" # The string itself.
哦,服务仅适用于日期为1986年1月19日及以后的XT,AT,EGA和PC敞篷车。但我想这不会造成任何问题,除非你正在处理一件严重的旧垃圾; -J
答案 2 :(得分:1)
;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
答案 3 :(得分:0)
要更改光标位置:
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的segmentaddress。
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
未经测试,但我希望没有错误。