61、BIOS 级编程与图形绘制

BIOS 级编程与图形绘制

1. BIOS 级编程基础

在 BIOS 级编程中,有几个实用的过程值得我们关注。

1.1 光标移动与屏幕操作过程

  • AdvanceCursor 过程 :该过程用于将光标向右移动指定的列数,且不会换行。接收参数 CX 为要移动的列数,不返回值。以下是其代码实现:
AdvanceCursor PROC
;
; Advances the cursor n columns to the right.
; (Cursor does not wrap around to the next line.)
; Receives: CX = number of columns
; Returns: nothing
;--------------------------------------------------
pusha
L1:
push
cx
; save loop counter
mov
ah,3      
; get cursor position
mov
bh,0
; into DH, DL
int
10h
; changes CX register!
inc
dl        
; increment column
mov
ah,2      
; set cursor position
int
10h
pop
cx
; restore loop counter
loop
L1
; next column
popa
ret
AdvanceCursor ENDP
  • Gotoxy 过程 :用于设置视频页面 0 上的光标位置。接收参数 DH DL 分别为行和列,不返回值。代码如下:
Gotoxy PROC
;
; Sets the cursor position on video page 0.
; Receives: DH,DL = row, column
; Returns: nothing
;---------------------------------------------------
pusha
mov
ah,2
; set cursor position
mov
bh,0
; video page 0
int
10h
popa
ret
Gotoxy ENDP
  • Clrscr 过程 :用于清除屏幕并将光标定位在视频页面 0 的第 0 行第 0 列。不接收参数,不返回值。代码如下:
Clrscr PROC
;
; Clears the screen (video page 0) and locates the
; cursor at row 0, column 0.
; Receives: nothing
; Returns:  nothing
;-------------------------------------------------------
pusha
mov
ax,0600h    
; scroll entire window up
mov
cx,0        
; upper left corner (0,0)
mov
dx,184Fh    
; lower right corner (24,79)
mov
bh,7        
; normal attribute
int
10h         
; call BIOS
mov
ah,2        
; locate cursor at 0,0
mov
bh,0        
; video page 0
mov
dx,0
; row 0, column 0
int
10h
popa
ret
Clrscr ENDP

1.2 相关问题回顾

以下是一些关于视频显示访问和 INT 10h 功能的常见问题及解答:
| 问题 | 解答 |
| ---- | ---- |
| 视频显示的三种访问级别是什么? | 未提及具体内容 |
| 哪种访问级别产生最快的输出? | 未提及具体内容 |
| 如何以全屏模式运行程序? | 未提及具体内容 |
| 计算机在 MS - DOS 中启动时,默认视频模式是什么? | 未提及具体内容 |
| 视频显示上的每个位置为单个字符保存什么信息? | 未提及具体内容 |
| 生成视频显示上的任何颜色需要哪些电子束? | 未提及具体内容 |
| 显示视频属性字节中前景色和背景色的映射。 | 未提及具体内容 |
| 哪个 INT 10h 功能在屏幕上定位光标? | INT 10h 功能 2 |
| 哪个 INT 10h 功能向上滚动矩形窗口? | INT 10h 功能 6 |
| 哪个 INT 10h 功能在当前光标位置写入字符和属性? | 未提及具体内容 |
| 哪个 INT 10h 功能设置光标大小? | 未提及具体内容 |
| 哪个 INT 10h 功能获取当前视频模式? | INT 10h 功能 0Fh |
| 使用 INT 10h 设置光标位置需要哪些参数? | AH = 2,BH 为视频页面,DH 为行,DL 为列 |
| 如何隐藏光标? | 未提及具体内容 |
| 向上滚动窗口需要哪些参数? | AX = 0600h,CX 为左上角坐标,DX 为右下角坐标,BH 为属性 |
| 在当前光标位置写入字符和属性需要哪些参数? | 未提及具体内容 |
| 哪个 INT 10h 功能设置闪烁/强度模式? | 未提及具体内容 |
| 使用 INT 10h 功能 6 清除屏幕时,应将哪些值移动到 AH 和 AL? | AH = 06h,AL = 00h |

2. 使用 INT 10h 绘制图形

2.1 INT 10h 图形模式

在使用 INT 10h 绘制图形之前,需要将视频适配器设置为标准图形模式之一。以下是 INT 10h 识别的视频图形模式:
| 模式 | 分辨率(像素) | 颜色数量 |
| ---- | ---- | ---- |
| 6 | 640 × 200 | 2 |
| 0Dh | 320 × 200 | 16 |
| 0Eh | 640 × 200 | 16 |
| 0Fh | 640 × 350 | 2 |
| 10h | 640 × 350 | 16 |
| 11h | 640 × 480 | 2 |
| 12h | 640 × 480 | 16 |
| 13h | 320 × 200 | 256 |
| 6Ah | 800 × 600 | 16 |

2.2 INT 10h 像素相关功能

2.2.1 写入图形像素(0Ch)

INT 10h 功能 0Ch 用于在视频控制器处于图形模式时在屏幕上绘制像素。但该功能执行速度较慢,尤其是绘制大量像素时。
- 接收参数
- AH = 0Ch
- AL = 像素值
- BH = 视频页面
- CX = x 坐标
- DX = y 坐标
- 返回值 :无
- 示例调用

mov  ah,0Ch
mov  al,pixelValue
mov  bh,videoPage 
mov  cx,x_coord
mov  dx,y_coord
int  10h
  • 注意事项 :视频显示必须处于图形模式。像素值范围和坐标范围取决于当前图形模式。如果 AL 的第 7 位被设置,新像素将与当前像素内容进行异或运算(允许擦除像素)。
2.2.2 读取图形像素(0Dh)

INT 10h 功能 0Dh 用于从屏幕上的给定行和列位置读取图形像素,并在 AL 中返回像素值。
- 接收参数
- AH = 0Dh
- BH = 视频页面
- CX = x 坐标
- DX = y 坐标
- 返回值 AL = 像素值
- 示例调用

mov   ah,0Dh
mov   bh,0               ; video page 0
mov   cx,x_coord
mov   dx,y_coord
int   10h
mov   pixelValue,al
  • 注意事项 :视频显示必须处于图形模式。像素值范围和坐标范围取决于当前图形模式。

2.3 DrawLine 程序

DrawLine 程序使用 INT 10h 切换到图形模式,以文本形式写入程序名称,并绘制一条水平直线。以下是完整的程序代码:

TITLE DrawLine Program              (DrawLine.asm)
; This program draws text and a straight line in graphics mode.
INCLUDE Irvine16.inc
;------------ Video Mode Constants -------------------
Mode_06 = 6
; 640 X 200,  2 colors
Mode_0D = 0Dh
; 320 X 200, 16 colors
Mode_0E = 0Eh
; 640 X 200, 16 colors
Mode_0F = 0Fh
; 640 X 350,  2 colors
Mode_10 = 10h
; 640 X 350, 16 colors
Mode_11 = 11h
; 640 X 480,  2 colors
Mode_12 = 12h
; 640 X 480, 16 colors
Mode_13 = 13h
; 320 X 200, 256 colors
Mode_6A = 6Ah
; 800 X 600, 16 colors
.data
saveMode  BYTE  ?
; save the current video mode
currentX  WORD 100
; column number (X-coordinate)
currentY  WORD 100
; row number (Y-coordinate)
COLOR = 1001b
; line color (cyan)
progTitle BYTE "DrawLine.asm"
TITLE_ROW = 5
TITLE_COLUMN = 14
; When using a 2-color mode, set COLOR to 1 (white)
.code
main PROC
mov
ax,@data
mov
ds,ax
; Save the current video mode.
mov
ah,0Fh
int
10h
mov
saveMode,al
; Switch to a graphics mode.
mov
ah,0   
; set video mode
mov
al,Mode_6A
int
10h
; Write the program name, as text.
mov
ax,SEG progTitle
; get segment of progTitle
mov
es,ax
; store in ES
mov
bp,OFFSET progTitle
mov
ah,13h
; function: write string
mov
al,0
; mode: only character codes
mov
bh,0
; video page 0
mov
bl,7
; attribute = normal
mov
cx,SIZEOF progTitle
; string length
mov
dh,TITLE_ROW
; row (in character cells)
mov
dl,TITLE_COLUMN
; column (in character cells)
int
10h
; Draw a straight line.
LineLength = 100
mov
dx,currentY
mov
cx,LineLength
; loop counter
L1:
push
cx
mov
ah,0Ch  
; write pixel
mov
al,COLOR    
; pixel color
mov
bh,0
; video page 0
mov
cx,currentX
int
10h
inc
currentX
;inc
color
; enable to see a multi-color line
pop
cx
Loop
L1
; Wait for a keystroke.
mov
ah,0
int
16h
; Restore the starting video mode.
mov
ah,0   
; set video mode
mov
al,saveMode   
; saved video mode
int
10h
exit
main ENDP
END main

2.4 Cartesian Coordinates 程序

Cartesian Coordinates 程序将视频适配器设置为模式 6Ah(800 × 600,16 色),并绘制笛卡尔坐标系的 X 轴和 Y 轴。以下是程序代码:

TITLE Cartesian Coordinates                 (Pixel2.asm)
; This program switches into 800 X 600 graphics mode and
; draws the X and Y axes of a Cartesian coordinate system.
; Switch to full-screen mode before running this program.
; Color constants are defined in Irvine16.inc.
INCLUDE Irvine16.inc
Mode_6A = 6Ah
; 800 X 600, 16 colors
X_axisY = 300
X_axisX = 50
X_axisLen = 700
Y_axisX = 400
Y_axisY = 30
Y_axisLen = 540
.data
saveMode BYTE ?
.code
main PROC
mov
ax,@data
mov
ds,ax
; Save the current video mode
mov
ah,0Fh
; get video mode
int
10h
mov
saveMode,al
; Switch to a graphics mode
mov
ah,0   
; set video mode
mov
al,Mode_6A
; 800 X 600, 16 colors
int
10h
; Draw the X-axis
mov
cx,X_axisX
; X-coord of start of line
mov
dx,X_axisY
; Y-coord of start of line
mov
ax,X_axisLen 
; length of line
mov
bl,white
; line color (see IRVINE16.inc)
call
DrawHorizLine
; draw the line now
; Draw the Y-axis
mov
cx,Y_axisX
; X-coord of start of line
mov
dx,Y_axisY
; Y-coord of start of line
mov
ax,Y_axisLen
; length of line
mov
bl,white
; line color
call
DrawVerticalLine
; draw the line now
; Wait for a keystroke
mov
ah,10h
; wait for key
int
16h
; Restore the starting video mode
mov
ah,0   
; set video mode
mov
al,saveMode   
; saved video mode
int
10h
exit
main endp
;------------------------------------------------------
DrawHorizLine PROC
;
; Draws a horizontal line starting at position X,Y with
; a given length and color.
; Receives: CX = X-coordinate, DX = Y-coordinate,
;           AX = length, and BL = color
; Returns: nothing
;------------------------------------------------------
.data
currX WORD ?
.code
pusha
mov
currX,cx
; save X-coordinate
mov
cx,ax
; loop counter
DHL1:
push
cx
; save loop counter
mov
al,bl
; color
mov
ah,0Ch
; draw pixel
mov
bh,0
; video page
mov
cx,currX
; retrieve X-coordinate
int
10h
inc
currX
; move 1 pixel to the right
pop
cx
; restore loop counter
loop
DHL1
popa
ret
DrawHorizLine ENDP
;------------------------------------------------------
DrawVerticalLine PROC
;
; Draws a vertical line starting at position X,Y with
; a given length and color.
; Receives: CX = X-coordinate, DX = Y-coordinate,
;           AX = length, BL = color
; Returns: nothing
;------------------------------------------------------
.data
currY WORD ?
.code
pusha
mov
currY,dx
; save Y-coordinate
mov
currX,cx
; save X-coordinate
mov
cx,ax
; loop counter
DVL1:
push
cx
; save loop counter
mov
al,bl
; color
mov
ah,0Ch
; function: draw pixel
mov
bh,0
; set video page
mov
cx,currX
; set X-coordinate
mov
dx,currY
; set Y-coordinate
int
10h
; draw the pixel
inc
currY
; move down 1 pixel
pop
cx
; restore loop counter
loop
DVL1
popa
ret
DrawVerticalLine ENDP
END main

2.5 笛卡尔坐标转换为屏幕坐标

笛卡尔图上的点与 BIOS 图形系统使用的绝对坐标不对应。可以使用以下公式将笛卡尔坐标 (X, Y) 转换为屏幕坐标 (sx, sy)
- sx = (sOrigX + X)
- sy = (sOrigY - Y)
其中, sOrigX sOrigY 是笛卡尔坐标系原点的屏幕坐标。

例如,在 Cartesian Coordinates 程序中,直线相交于 sOrigX = 400 sOrigY = 300 ,将原点置于屏幕中间。以下是一些测试点的转换结果:
| 笛卡尔坐标 (X, Y) | 转换公式 (sOrigX + X, sOrigY - Y) | 屏幕坐标 (sx, sy) |
| ---- | ---- | ---- |
| (0, 100) | (400 + 0, 300 - 100) | (400, 200) |
| (100, 0) | (400 + 100, 300 - 0) | (500, 300) |
| (0, -100) | (400 + 0, 300 - (-100)) | (400, 400) |
| (-100, 0) | (400 + (-100), 300 - 0) | (300, 300) |

2.6 相关问题回顾

问题 解答
哪个 INT 10h 功能在视频显示上绘制单个像素? INT 10h 功能 0Ch
使用 INT 10h 绘制单个像素时,必须在 AL BH CX DX 寄存器中放置哪些值? AL = 像素值, BH = 视频页面, CX = x 坐标, DX = y 坐标
使用 INT 10h 绘制像素的主要缺点是什么? 执行速度慢
编写将视频适配器设置为模式 11h 的 ASM 语句。 mov ah, 0; set video mode
mov al, 11h; mode 11h
int 10h; call BIOS routine
哪个视频模式是 800 × 600 像素,16 色? 模式 6Ah
将笛卡尔 X 坐标转换为屏幕像素坐标的公式是什么? sx = (sOrigX + X)
如果笛卡尔原点位于屏幕坐标 sy = 250 sx = 350 ,将以下笛卡尔点 (X, Y) 转换为屏幕坐标 (sx, sy)
a. (0, 100)
b. (25, 25)
c. (-200, -150)
a. (350, 150)
b. (375, 225)
c. (150, 400)

3. 内存映射图形

3.1 Mode 13h:320 X 200,256 色

视频模式 13h 是用于内存映射图形最容易使用的模式。屏幕像素被映射为一个二维字节数组,每个像素 1 个字节。该数组从屏幕左上角的像素开始,沿顶行延续 320 个字节。偏移量 320 处的字节映射到屏幕第二行的第一个像素,然后依次沿屏幕继续。其余行以类似方式映射。数组的最后一个字节映射到屏幕右下角的像素。每个像素使用一个完整字节的原因是,该字节保存着对 256 种不同颜色值之一的引用。

使用 OUT 指令将像素和颜色值传输到视频适配器硬件。16 位端口地址分配给 DX ,发送到端口的值在 AL AX EAX 中。例如,视频调色板位于端口地址 3C8h。以下指令将值 20h 发送到该端口:

mov dx,3c8h ; port address
mov al,20h ; value to be output
out dx,al ; send value to port

在模式 13h 中,颜色的有趣之处在于每个颜色整数并不直接表示一种颜色,而是表示一个称为调色板的颜色表的索引。调色板中的每个条目由三个整数值(0 到 63)组成,即 RGB(红、绿、蓝)。调色板中的条目 0 控制屏幕的背景颜色。

通过这种方案可以创建 262,144 种不同的颜色(64³)。在给定时间只能显示 256 种不同的颜色,但程序可以在运行时修改调色板以改变显示颜色。现代操作系统(如 Windows 和 Linux)提供(至少)24 位颜色,其中每个 RGB 值的范围是 0 到 255,这种方案提供 256³(1670 万)种不同的颜色。

RGB 颜色基于光的加性混合,与混合液体颜料时使用的减性方法相反。例如,通过将所有颜色强度级别保持为零来创建黑色。另一方面,通过将所有颜色级别设置为 63(最大值)来创建白色。实际上,当三个级别相等时,会得到不同深浅的灰色:
| 红色 | 绿色 | 蓝色 | 颜色 |
| ---- | ---- | ---- | ---- |
| 0 | 0 | 0 | 黑色 |
| 20 | 20 | 20 | 深灰色 |
| 35 | 35 | 35 | 中灰色 |
| 50 | 50 | 50 | 浅灰色 |
| 63 | 63 | 63 | 白色 |

纯色通过将除一个颜色级别之外的所有颜色级别设置为零来创建。要获得浅色,以相等的量增加其他两种颜色。以下是红色的变化示例:
| 红色 | 绿色 | 蓝色 | 颜色 |
| ---- | ---- | ---- | ---- |
| 63 | 0 | 0 | 亮红色 |
| 10 | 0 | 0 | 暗红色 |
| 30 | 0 | 0 | 中红色 |
| 63 | 40 | 40 | 粉红色 |

同样,可以创建亮蓝色、深蓝色、浅蓝色、亮绿色、深绿色和浅绿色。当然,也可以以其他比例混合两种颜色来创建诸如品红色和淡紫色等颜色。以下是一些示例:
| 红色 | 绿色 | 蓝色 | 颜色 |
| ---- | ---- | ---- | ---- |
| 0 | 30 | 30 | 青色 |
| 30 | 30 | 0 | 黄色 |
| 30 | 0 | 30 | 品红色 |
| 40 | 0 | 63 | 淡紫色 |

3.2 内存映射图形程序

以下是一个使用直接内存映射在模式 13h 下在屏幕上绘制一行 10 个像素的程序:

; Memory Mapped Graphics, Mode 13        (Mode13.asm)
INCLUDE Irvine16.inc
VIDEO_PALLETE_PORT = 3C8h
COLOR_SELECTION_PORT = 3C9h
COLOR_INDEX = 1
PALLETE_INDEX_BACKGROUND = 0
SET_VIDEO_MODE = 0
GET_VIDEO_MODE = 0Fh
VIDE0_SEGMENT = 0A000h
WAIT_FOR_KEYSTROKE = 10h
MODE_13 = 13h
.data
saveMode BYTE ? ; saved video mode
xVal     WORD ? ; x-coordinate
yVal     WORD ? ; y-coordinate
msg      BYTE "Welcome to Mode 13!",0
.code
main PROC
mov  ax,@data
mov  ds,ax
call SetVideoMode
call SetScreenBackground
; Display a greeting message.
mov  edx,OFFSET msg
call WriteString
call Draw_Some_Pixels
call RestoreVideoMode
exit
main ENDP

;------------------------------------------------
SetScreenBackground PROC
;
; Sets the screen's background color. Video
; palette index 0 is the background color.
;------------------------------------------------
mov dx,VIDEO_PALLETE_PORT
mov al,PALLETE_INDEX_BACKGROUND
out dx,al
; Set the screen background color to dark blue.
mov dx,COLOR_SELECTION_PORT
mov al,0 ; red
out dx,al
mov al,0 ; green
out dx,al
mov al,35 ; blue (intensity 35/63)
out dx,al
ret
SetScreenBackground endp

;-----------------------------------------------
SetVideoMode PROC
;
; Saves the current video mode, switches to a
; new mode, and points ES to the video segment.
;-----------------------------------------------
mov ah,GET_VIDEO_MODE
int 10h
mov saveMode,al ; save it
mov ah,SET_VIDEO_MODE
mov al,MODE_13 ; to mode 13h
int 10h
push VIDE0_SEGMENT ; video segment address
pop es ; ES points to video segment
ret
SetVideoMode ENDP

;---------------------------------------------
RestoreVideoMode PROC
;
; Waits for a key to be pressed and restores
; the video mode to its original value.
;----------------------------------------------
mov ah,WAIT_FOR_KEYSTROKE
int 16h
mov ah,SET_VIDEO_MODE ; reset video mode
mov al,saveMode ; to saved mode
int 10h
ret
RestoreVideoMode ENDP

;-----------------------------------------------
Draw_Some_Pixels PROC
; 此处代码未给出完整,推测后续会有绘制像素的具体逻辑
ret
Draw_Some_Pixels ENDP
END main

该程序的执行流程如下:

graph LR
    A[开始] --> B[设置视频模式]
    B --> C[设置屏幕背景]
    C --> D[显示问候消息]
    D --> E[绘制一些像素]
    E --> F[恢复视频模式]
    F --> G[结束]

3.3 总结

本文介绍了 BIOS 级编程中的光标移动和屏幕操作过程,如 AdvanceCursor Gotoxy Clrscr 过程。还详细阐述了使用 INT 10h 绘制图形的方法,包括设置图形模式、绘制像素、绘制直线以及笛卡尔坐标与屏幕坐标的转换。最后,介绍了内存映射图形,重点讲解了模式 13h 的特点和使用方法,并给出了相应的程序示例。

通过这些知识和代码示例,我们可以看到 BIOS 级编程和图形绘制在底层硬件交互方面的强大功能。在实际应用中,可以根据具体需求选择合适的图形模式和绘制方法,以实现高效、美观的图形输出。同时,对于内存映射图形,虽然它提供了更高效的图形绘制方式,但需要对硬件和内存映射有更深入的理解。

希望这些内容能帮助你更好地掌握 BIOS 级编程和图形绘制的相关知识,在实际项目中灵活运用。

内容概要:本文围绕六自由度机械臂的人工神经网络(ANN)设计展开,重点研究了正向逆向运动学求解、正向动力学控制以及基于拉格朗日-欧拉法推导逆向动力学方程,并通过Matlab代码实现相关算法。文章结合理论推导仿真实践,利用人工神经网络对复杂的非线性关系进行建模逼近,提升机械臂运动控制的精度效率。同时涵盖了路径规划中的RRT算法B样条优化方法,形成从运动学到动力学再到轨迹优化的完整技术链条。; 适合人群:具备一定机器人学、自动控制理论基础,熟悉Matlab编程,从事智能控制、机器人控制、运动学六自由度机械臂ANN人工神经网络设计:正向逆向运动学求解、正向动力学控制、拉格朗日-欧拉法推导逆向动力学方程(Matlab代码实现)建模等相关方向的研究生、科研人员及工程技术人员。; 使用场景及目标:①掌握机械臂正/逆运动学的数学建模ANN求解方法;②理解拉格朗日-欧拉法在动力学建模中的应用;③实现基于神经网络的动力学补偿高精度轨迹跟踪控制;④结合RRTB样条完成平滑路径规划优化。; 阅读建议:建议读者结合Matlab代码动手实践,先从运动学建模入手,逐步深入动力学分析神经网络训练,注重理论推导仿真实验的结合,以充分理解机械臂控制系统的设计流程优化策略。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值