【问题标题】:Line feed (0AH) messing up with video interrupt INT 10H换行 (0AH) 与视频中断 INT 10H 混淆
【发布时间】:2012-09-08 23:04:20
【问题描述】:

我正在尝试编写一个使用嵌套循环的简单代码,以以下模式打印字符,

XXXXXXXXXX
XXXXXXXXX
XXXXXXXX
XXXXXXX
XXXXXX
XXXXX
XXXX
XXX
XX
X

这是代码,代码工作得很好

   MOV AX, @DATA                ; INITIALIZE DS
    MOV DS, AX



    ; PRINT X

    MOV CX,10
    MOV BX,10

    L2:
        PUSH CX
        MOV CX,BX
            L1:
                MOV DX, OFFSET HW            ; LOAD THE STRING
                MOV AH,09H
                INT 21H
            Loop L1
        SUB BX,01
        POP CX

        MOV DX,0AH
        MOV AH,02H
        INT 21H
    Loop L2


    MOV AH, 4CH                  ; RETURN CONTROL TO DOS
    INT 21H

但是,一旦我使用视频中断清屏,输出就会完全混乱,

这是输出,

XXXXXXXXXX
          XXXXXXXXX
                   XXXXXXXX
                           XXXXXXX
                                  XXXXXX
                                        XXXXX
                                             XXXX
                                                 XXX
                                                    XX
                                                      X

这是它的代码,

.MODEL SMALL
 .STACK 100H

 .DATA
    HW  DB  "X$"

 .CODE
   MAIN PROC

    MOV AX, @DATA                ; INITIALIZE DS
    MOV DS, AX

    ; CLEAR SCREEN

    MOV AH, 06H
    MOV AL, 00H
    MOV CX, 00H
    MOV DH, 25
    MOV DL, 80
    MOV BH, 0FH 
    INT 10H

    ; PRINT X

    MOV CX,10
    MOV BX,10

    L2:
        PUSH CX
        MOV CX,BX
            L1:
                MOV DX, OFFSET HW            ; LOAD THE STRING
                MOV AH,09H
                INT 21H
            Loop L1
        SUB BX,01
        POP CX

        MOV DX,0AH
        MOV AH,02H
        INT 21H
    Loop L2





    MOV AH, 4CH                  ; RETURN CONTROL TO DOS
    INT 21H

   MAIN ENDP
 END MAIN

但是当我删除每次迭代后留下一行的换行符时,即

MOV DX,0AH
MOV AH,02H
INT 21H

输出符合预期,

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

我不明白清除屏幕代码与换行代码有什么关系?为什么他们互相搞砸了。 ?

当我使用光标位置设置代码而不是清除屏幕时,也会出现同样的问题,

MOV AH, 02H
MOV BH, 00H
MOV CX, 0000H
MOV DX, 0C22H    
INT 10H

输出假设是我屏幕中间的以下内容,

XXXXXXXXXX
XXXXXXXXX
XXXXXXXX
XXXXXXX
XXXXXX
XXXXX
XXXX
XXX
XX
X

但显示如下,

                                 XXXXXXXXXX
                                           XXXXXXXXX
                                                    XXXXXXXX
                                                            XXXXXXX
                                                                   XXXXXX
                                                                         XXXXX
                                                                              X
XX
  XXX
     XX
       X

【问题讨论】:

  • 你要求换行,你得到了换行。 0Dh控制字符为“回车”。
  • 换行不等于转到下一行,即 \n ?
  • 确实如此,直接向下。不,这不是 Unix 或 C。
  • 那么它有什么问题,至少指出一下?
  • 换行只是向上滚动页面,将插入符号(或“光标”)留在同一列。另一方面,回车将关心的内容移动到行首,但不会向上滚动页面。您需要组合这两个控制字符以向上滚动页面并将插入符号移动到行首,以任何顺序。这就是电传打字机在过去的工作方式。想象一台打印机打印出字符并被这些控制字符控制。

标签: assembly x86 interrupt


【解决方案1】:

部分代码:

MOV AH, 02H
MOV BH, 00H  ----> this is page number
MOV CX, 0000H
MOV DX, 0C22H   --->why such big number for column number?
INT 10H

你为什么使用页面 0h?确定您正在使用该页面?如何?我知道它已经完成了:

视频 - 获取当前视频模式

AH = 0Fh
int 10h
Return:
AH = number of character columns
AL = display mode (see #00010 at AH=00h)
BH = active page (see AH=05h) ---------------->you will need this

视频 - 设置光标位置

AH = 02h
BH = page number  <--------------now you know what to put here
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)
int 10h

Return:
Nothing

来源:Ralph Brown's interrupts page

显示页面

图形适配器可以存储多个屏幕的文本数据(这是因为显示一个屏幕的图形需要比文本更多的内存)。为了充分利用显示内存,它被划分为显示页面。一个显示页面可以保存一个屏幕的数据。页面从 0 开始编号;可用页数取决于适配器和选择的显示模式。

对于 80 x 25 文本模式,每个显示页面为 4 KB。文本模式的显示页面 0 从地址 B800:0000h 开始。

活动显示页面是当前正在显示的页面。对于 80 x 25 文本模式,内存要求为 80 x 25 = 2000 字 = 4000 字节(即显示器不会使用显示页面内存中的所有 4 KB 或 4096 字节)。

视频控制器在屏幕左上角(0,0)显示活动显示页面的第一个WORD,然后在(1,0)显示下一个WORD,以此类推,逐行显示屏幕.屏幕显示可以看成二维数组的图像。

INT 10h Video Functions

00h: Set Video Mode.  Selects the video mode and clears the screen automatically.
Input:
    AH = 0
    AL = 3        ; mode 3 = 80 cols   x 25 rows color text
                  ; to avoid clearing the screen use mode 83h to set high bit
    AL = 6        ; sets medium resolution (640 x 200) graphics mode

When BIOS sets the display mode, it also clears the screen.

01h: Change Cursor Size
Input:
   AH = 1
   CH = starting scan line
   CL = ending scan line

The text mode cursor is displayed as a small dot array at a screen position. For the MDA and EGA, the dot array is 14 rows (0-13). For the CGA, the array is 8 rows (0-7). Normally rows 6 and 7 are lit for the CGA and rows 11 and 12 for the MDA/EGA cursor.

02h: Set Cursor Position.  Move cursor to specified position.
Input:
    AH = 2
    DH = row  (0-24)
    DL = col  (0-79 for 80x25 display)
    BH = video page number (usually 0)

03h: Get Cursor Position.   Return row and column position of cursor.
Input:
    AH = 3
    BH = video page number (usually 0)

Output:
    DH = row                     ; position
    DL = col
    CH = starting scan line     ; size
    CL = ending scan line

06h: Scroll the Screen or a Window Up
Input:
    AH = 6
    AL = number of lines to scroll (0 => whole screen)
    BH = attribute for blank lines
    CH, CL = row, column for upper left corner
    DH, DL = row, column for lower right window

Scrolling the screen up one line means to move each display line UP one row and insert a blank line at the bottom of the screen. The previous top row disappears from the screen.

The whole screen or any rectangular area (window) may be scrolled. AL contains the number of lines to scroll. If AL = 0, all the lines are scrolled and this clears the screen or window.

Example: Clear the screen to black for the 80x25 display.

MOV AH, 6      ; scroll up function
XOR AL, AL     ; clear entire screen
XOR CX, CX     ; upper left corner is (0,0)
MOV DX, 184FH  ; lower right corner is (4Fh, 18H)
MOV BH, 7      ; normal video attribute
INT 10H        ; clear screen

07h: Scroll the Screen/Window down
Input:
    AH = 7
    AL = number of lines to scroll (0 => whole screen)
    BH = attribute for blank lines
    CH, CL = row, column for upper left corner 
    DH, DL = row, column for lower right corner

Same as function 6, but lines are scrolled down instead of up.

08h: Read character at cursor. Can be used in either text or graphics mode.
Input:   AH = 8
         BH = page number
Output:  AH = attribute
         AL = ASCII code of character

09h: Write character and attribute.   Display any ASCII character at current position and set desired attribute.   Can be used in graphics or video mode.
Input:
    AH = 09
    AL = ASCII character code
    BH = video page number (usually 0)
    BL = attribute to be used. (In video mode, sets foreground (pixel) color)
    CX = repetition count

Note: cursor will not be moved beyond the last character displayed.

Also, if AL contains the ASCII code of a control character, a control function is not performed --- a display symbol is shown instead.

Example: change the attribute of the character under the cursor to reverse video for monochrome display.

        MOV AH, 8     ; read character
        XOR BH, BH    ; on page 0
        INT 10H       ; character in AL, attribute in AH

        MOV AH, 9     ; display character
        MOV CX, 1     ; display 1 character
        MOV BL, 70H   ; reverse video attribute
        INT 10H       ; display character  

0Ah: Write character.  Display any ASCII character at current position without changing the current attribute.  Can be used in text or video mode.
Input:
    AH = 0Ah
    AL = ASCII character code
    BH = video page number (usually 0)
    CX = repetition count

0Eh: Display Character and Advance Cursor
Input:   AH = 0Eh
         AL = ASCII code of character
         BH = page number
         BL = foreground color (graphics mode only)

This function displays the character in AL and advances the cursor to the next position in the row, or if at the end of a row, it sends it to the beginning of the next row. If the cursor is in the lower right corner, the screen is scrolled up and the cursor is set to the beginning of the last row. This is the BIOS function used by INT 21h, function 2, to display a character. The control characters bell (07h), backspace (08h), line feed (0Ah), and carriage return (0Dh) cause control functions to be performed.

Source is here.

【讨论】:

  • 我完全没听懂你的意思:/至少你想说什么
  • 我读到 0fh 用于背景和前景色,这就是为什么我将 0 用于黑色 bg 和 F 用于白色 FG。如果是关于页码应该是什么而不是 0f ?我无法获取我的页面,请提供示例代码以获取我所在的页面
  • 改变BH的值只是改变页面的颜色
  • MOV DX, 0C22H --->OC 是 ROW 而 22 是coloumn,这实际上是我的DOS屏幕的中心,这就是为什么值那么大。我不明白你再次提到页码 n 是在说什么
猜你喜欢
  • 1970-01-01
  • 2020-02-08
  • 2013-10-20
  • 2014-03-08
  • 2020-09-05
  • 2015-07-23
  • 2014-07-09
  • 1970-01-01
  • 2013-01-25
相关资源
最近更新 更多