首页 文章

使用0Eh 10h中断时,为什么文本不变色?

提问于
浏览
0

我正在使用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

4 回答

  • 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
    
  • 0

    我认为比标记为接受的更好的想法是使用中断10h的功能13h . 该函数应该将整个字符串与属性(颜色)一起发送到屏幕 . 这个函数有四个 modes of operation ,在 AL 寄存器中指定 .

    AL = 00h:为BL中的属性分配所有字符;不要更新光标位置 . AL = 01h:为BL中的属性分配所有字符;更新光标位置 . AL = 02h:在字符串中使用属性;不要更新光标位置 . AL = 03h:在字符串中使用属性;更新光标位置 .

    因此,您可以通过在 BL 中为模式 00h01h 指定属性来为整个字符串使用相同的属性(颜色),或者将字符串本身中的属性混合以使用不同的属性打印每个字符 .

    我用这种方法看到的唯一缺点就是你必须事先知道字符串的长度(把它放入 CX ),因为这个函数不能用于以空字符结尾的字符串 .
    但是,另一方面,在字符之前存储字符串的一个字节长度而不是字符之后的空字符可以有一些好处:你不要占用比空终止符更多的地方 . 即使是两个字节的长度也不是浪费 . 您可以将两个字节的长度直接加载到 CX 中 . 您也可以使用一个字节长度执行相同的操作,但请务必在之后清除 CH .

    拥有该属性的每个字符的能力属性也有时是有用的 .

    其他寄存器照常:
    BH 是页码 .
    DX 是在屏幕上启动字符串的位置: DH:DL = Y:X
    ES:BP 指向内存中字符串的第一个字符 .

    如果使用电传打字模式( 01h03h ),则可正确解释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日及之后的AT,EGA和PC敞篷车的XT . 但我想它不会造成任何问题,除非你正在处理一件严重的旧垃圾; -J

  • 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
    
  • 1

    要更改光标位置:

    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
    

    没有经过测试,但我希望没有错误 .

相关问题