Why isn't the text colored when using the 0Eh 10h interrupt?

前端 未结 4 824
别跟我提以往
别跟我提以往 2020-12-22 07:43

I\'m using the 10h interrupt with AH as 0Eh to output \"Hello World!\" The text is ouputted but its not colored. I\'m running it on qemu-system-x86_64, assembling with NASM,

相关标签:
4条回答
  • 2020-12-22 08:21

    I was able to print with color by using the 09 for the 10h interrupt, instead of 0E. You do, however, have to change the cursor position after each character to use this method. Here is the working code.

         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 讨论(0)
  • 2020-12-22 08:25
    ;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   
    
    0 讨论(0)
  • 2020-12-22 08:35

    For to change the cursor position:

    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
    

    I like it more to write directly into the segmentaddress of 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
    

    Not tested, but i hope no mistakes slept in.

    0 讨论(0)
  • 2020-12-22 08:39

    I think a better idea than the one marked as accepted is to use function 13h of interrupt 10h. This function is supposed to send entire strings to the screen, along with attributes (colors). There are four modes of operation for this function, specified in the AL register.

    AL=00h: Assign all characters the attribute in BL; do not update the cursor position.
    AL=01h: Assign all characters the attribute in BL; update the cursor position.
    AL=02h: Use attributes in string; do not update the cursor position.
    AL=03h: Use attributes in string; update the cursor position.

    So you can either use the same attribute (colors) for the entire string by specifying the attribute in BL for modes 00h or 01h, or intermingle the attributes in the string itself to print each character with a different attribute.

    The only drawback I see with this approach is that you have to know the length of the string upfront (to put it into CX), since this function doesn't work with null-terminated strings.
    But, on the other hand, storing a one-byte length of the string preceding its characters instead of the null character after its characters could have some benefits: You don't need to traverse the entire string to know its length; and a one-byte length won't take any more place than the null terminator. Even a two-byte length is not much a waste. You can load a two-byte length directly into CX. You can do the same with a one-byte length, too, but make sure to clear out the CH afterwards.

    Having the ability attribute each character of the string alone also could be useful sometimes.

    Other registers are as usual:
    BH is the page number.
    DX is where to start the string on the screen: DH:DL = Y:X
    ES:BP points to the first character of the string in memory.

    If you use the teletype modes (01h or 03h), ASCII control characters are properly interpreted instead of being printed as symbols. They also update the cursor position to the end of the string.

    To make it work continuously, you can use the function AH=03h to get the cursor position. It is made so that it loads the cursor position to the DH:DL, so it can be used afterwards directly in the subsequent call to AH=13h to print the string from that position. Here's how I do it:

    # 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.
    

    Calling (assuming the ES is properly set):

                   # 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
    

    The data section:

    msgHello:     .word 13                  # Length of the string.
                  .ascii "Hello, World!"    # The string itself.
    

    Oh, and service is available only for XTs dated 01/19/1986 and later, ATs, EGAs, and PC Convertibles. But I guess it won't pose any problem, unless you're dealing with a serious piece of old junk ;-J

    0 讨论(0)
提交回复
热议问题