【问题标题】:Video mode used by BIOSBIOS 使用的视频模式
【发布时间】:2014-03-24 02:59:41
【问题描述】:

编写 2 阶段引导加载程序并查看输出后:

第一阶段的输出(通过使用 BIOS 的int 10h 中断产生)与在保护模式下直接访问显存获得的白色(或者是灰色?)不同。

为什么会有所不同? BIOS 使用什么视频模式?

【问题讨论】:

标签: graphics operating-system bootloader bios


【解决方案1】:

BIOS 以模式 0 启动,颜色属性字节为 0x07(黑色背景,灰色前景)。第二个白色似乎是 0x0F,因为设置了亮位(0x08 是亮度位,只需将其添加到颜色中即可获得亮色)。

【讨论】:

    【解决方案2】:

    当 IBM PC 兼容计算机启动时,在 POST 之后,当 BIOS 准备好加载引导加载程序时,BIOS 视频模式为 3(二进制为 11)。我已经在几台计算机和 Bochs 2.6.8 上使用以下引导扇区程序(为 FASM 编写)对此进行了测试。

    ;
    ;
    ; This boot sector program invokes BIOS INT 10h AH=0Fh (get current video mode) and displays the results to the screen
    ;
    ;
      ; Preliminary directives so fasm knows how to generate the machine code
      ;
        format binary                             ; this directive tells fasm to write the generated code as a flat binary file
        use16                                     ; this directive tells fasm to generate 16-bit code
        org 0x7C00                                ; org directive tells fasm that the program will be loaded at 0x7C00, where the BIOS hands over control to the bootstrap code
    ;
    ;
      ; Get current video mode (INT 10h, function AH=0Fh)
      ;
        mov ah,0xF                                ; set AH to 0xF (AH=0Fh is the function for getting the current video mode)
        int 0x10                                  ; invoke BIOS interrupt 10h, function AH=0Fh to get the current video mode
    ;
    ;
      ; Display results to the screen
      ;
        ; Save the results for printing later
        ;
          mov dh,al                               ; save AL (the current video mode) to DH
          push bx                                 ; save BH to the stack
          push ax                                 ; save AH to the stack
        ;
        ; Display the value saved to DH (i.e. the current video mode, which was copied from AL to DH above)
        ;
          xor ax,ax                               ; set AX to 0 in order to set DS to 0
          mov ds,ax                               ; DS = 0 (SI works with DS to point to the address created by DS:SI)
          mov si,vid_mode_prompt                  ; set SI to point to the first character of the message to be printed
          mov cx,12                               ; set the counter (CX) to match the number of characters to print
          call print_string_procedure             ; save to the stack the address of the next instruction, then jump to the procedure called by this instruction
          call procedure_for_printing_DH          ; save to the stack the address of the next instruction, then jump to the procedure called by this instruction
        ;
        ; Display the value for the number of character columns used by the current video mode (pushed onto the stack from AH)
        ;
          ;xor ax,ax                               ; set AX to 0 in order to set DS to 0 (commented out, because AX is not needed to set DS, since DS is probably already 0)
          ;mov ds,ax                               ; DS = 0 (SI works with DS to point to the address created by DS:SI) (commented out, because DS is probably already 0)
          mov si,num_col_prompt                   ; set SI to point to the first character of the message to be printed
          mov cx,13                               ; set the counter (CX) to match the number of characters to print
          call print_string_procedure             ; save to the stack the address of the next instruction, then jump to the procedure called by this instruction
          pop dx                                  ; copy to DH the number of columns previously saved to the stack from AH
          call procedure_for_printing_DH          ; save to the stack the address of the next instruction, then jump to the procedure called by this instruction
        ;
        ; Display the value for the active display page (pushed onto the stack from BH)
        ;
          ;xor ax,ax                               ; set AX to 0 in order to set DS to 0 (commented out, because AX is not needed to set DS, since DS is probably already 0)
          ;mov ds,ax                               ; DS = 0 (SI works with DS to point to the address created by DS:SI) (commented out, because DS is probably already 0)
          mov si,display_page_prompt              ; set SI to point to the first character of the message to be printed
          mov cx,17                               ; set the counter (CX) to match the number of characters to print
          call print_string_procedure             ; save to the stack the address of the next instruction, then jump to the procedure called by this instruction
          pop dx                                  ; copy to DH the value of the active display page
          call procedure_for_printing_DH          ; save to the stack the address of the next instruction, then jump to the procedure called by this instruction
    ;
    ;
      ; End of program
      ;
        end_of_program:                           ; label for this section of code
        hlt                                       ; stops instruction execution and places the processor in a halted state
        jmp end_of_program                        ; jump to the label 'end_of_program'
    ;
    ;
      ;
      ;
      ; Procedures called by the program
      ;
      ;
        print_string_procedure:                   ; label for this section of code
        ;pusha                                     ; save all 8 general registers to the stack (commented out, because it is not necessary to save the values of the general registers)
        mov ah,0xE                                ; set AH to 0Eh (i.e. select teletype output)
        xor bh,bh                                 ; set display page number to 0
          start_of_print_loop:                    ; label for this section of code
          lodsb                                   ; load string byte (i.e. copy the string element pointed to by DS:SI to AL)
          int 0x10                                ; invoke BIOS interrupt 10h, function AH=0Eh to display the ASCII character stored in AL
          loop start_of_print_loop                ; decrement CX by 1, then jump to the specified label until CX=0
        ;popa                                      ; pop the contents of all eight general registers back from the stack (commented out, because popa corresponds with pusha, which has been commented out above)
        ret                                       ; transfer control back to the program that invoked the procedure using the address that was stored on the stack by the call instruction
      ;
        procedure_for_printing_DH:                ; label for this section of code
        ;pusha                                     ; save all 8 general registers to the stack (commented out, because it is not necessary to save the values of the general registers)
        ;mov ah,0xE                                ; set AH to 0Eh (i.e. select teletype output) (commented out, because the value in AH is already 0Eh)
        ;xor bh,bh                                 ; set display page number to 0 (commented out, because the value in BH is already 0)
        mov cx,4                                  ; set the counter (CX) to match the number of characters to print
        call start_print_DH_loop                  ; save to the stack the address of the next instruction, then jump to the procedure called by this instruction
        mov al,0x20                               ; set AL to print a space (ASCII code for a space is 0x20)
        int 0x10                                  ; invoke BIOS interrupt 10h, function AH=0Eh to display the ASCII character stored in AL
        mov cx,4                                  ; set the counter (CX) to match the number of characters to print
        call start_print_DH_loop                  ; save to the stack the address of the next instruction, then jump to the procedure called by this instruction
        ;popa                                      ; pop the contents of all eight general registers back from the stack (commented out, because popa corresponds with pusha, which has been commented out above)
        ret                                       ; transfer control back to the program that invoked the procedure using the address that was stored on the stack by the call instruction
      ;
        start_print_DH_loop:                      ; label for this section of code
        shl dh,1                                  ; shifts the bits in the DH register to the left by one bit; the last exited bit will be stored to the CF flag
        setc al                                   ; sets the AL register to match the value of the CF flag
        add al,0x30                               ; convert the number in AL (0 or 1) to ASCII
        int 0x10                                  ; invoke BIOS interrupt 10h, function AH=0Eh to display the ASCII character stored in AL
        loop start_print_DH_loop                  ; decrement CX by 1, then jump to the specified label until CX=0
        ret                                       ; transfer control back to the program that invoked the procedure using the address that was stored on the stack by the call instruction
    ;
    ;
      ;
      ;
      ; Data used by the program
      ;
      ;
        vid_mode_prompt:
        db 'Video mode: '                         ; 12 characters
        ;
        num_col_prompt:
        db 0xD,0xA,0xD,0xA,'Columns: '            ; 13 characters
        ;
        display_page_prompt:
        db 0xD,0xA,0xD,0xA,'Active page: '        ; 17 characters
    ;
    ;
      ; Padding and magic number
        times 510-($-$$) db 0
        dw 0xaa55
    

    Screenshot from Bochs 2.6.8 after compiling and running the above program

    Information from Wikipedia on INT 10H

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-02-16
      • 2012-05-08
      • 2013-01-25
      • 2011-03-08
      • 2020-08-14
      • 1970-01-01
      • 1970-01-01
      • 2011-04-07
      相关资源
      最近更新 更多