我有一个称为average
的变量,在我的DATASEG
中,它每次都会更改,因为用户每次都输入不同的输入。我想做的是进入图形模式(VGA),然后在此处打印您的平均值是:然后,平均值就知道如何更改为如下所示的图形模式:
mov ax, 13h
int 10h
在打印平均值之后,如果平均值高于75 ,我想在下方打印。您是个好学生,请继续努力,如果不是。别担心,您会变得更好!
提前致谢。
最佳答案
我假设: PC VGA x86 MS DOS 平台
不管是真实的还是仿真的都没有关系,除非您想要低级的 IO 访问,而在 DOSBOX 等仿真中可能无法正常使用...
因此,要在视频和文本模式之间切换,您需要使用VGA BIOS:
mov ax,mode ; here select which mode you want
int 16 ; this calls EGA/VGA/VESA BIOS
这里有许多video modes,这两个非常重要:
mode | type | segment | resolution | align
----------------------------------------------------
03 | text | B800h | 80x25 chars | 2 Byte
19 | video | A000h | 320x200x256 colors | 1 Byte
在视频模式
19
中,您可以通过访问段A000h
处的内存来打印/查看像素,其中偏移量的计算方式如下:offset = 320*y + x
320x200
模式完全适合64 KByte
段,因此您无需切换页面。这使其成为简单的asm gfx程序的理想选择。模式
3
是文本模式,其中每个字符的2 BYTEs
一个是颜色,另一个是扩展的 ASCII 代码。再次通过访问段WORD
处的B800h
来完成打印/预览,其中偏移量为:offset = (80*y + x) * 2
不确定两年前的两个字节是什么顺序,但是您可以轻松地测试在
A
上写入0B800:0000
是否会在左上角呈现A
或在0B800:0001
中呈现。文本模式下的IIRC颜色仅是调色板中的前16种颜色,而颜色字节可编码墨水纸的亮度和闪光。此文本模式也是 MS-DOS shell正在使用的默认模式,因此您应在程序退出之前将其重新设置。因此,您的程序应如下所示:
start:
mov ax,19 ; set video mode
int 16
mainloop:
; here your stuff
exit:
mov ax,3
int 16
ret
对于初学者,您可以将文本和视频模式结合起来……就像我在这里做的那样:
这是一个简单的游戏,菜单处于文本模式(打印很容易,只需将字符串复制到 VRAM 即可),而精灵图形游戏则处于
320x200x256c
视频模式。要以gfx模式打印时,首先需要在内存中添加一些字体。如果您查看 EGA / VGA BIOS 文档,则可以获取位于 EGA / VGA ROM中的字体,然后直接使用它。我还创建了此图像(使用Trident 9000 256 / 512KB VGA字体的IIRC),将其用作 OpenGL 和其他内容(无法访问 VGA BIOS 的等宽字体)的...
在这里GLSL example of using it for printing您可以将其移植到 CPU / VGA / asm,但在 CPU 上的打印要简单得多,不需要像 GLSL 片段这样的可怕内容。
因此,您只需要根据 ASCII 代码计算图像位置,并将其像素复制到 VRAM 中。在asm中粗略地拥有位图并不容易,更容易的是直接将其以二进制形式(作为
db
的集合),因此您可以编写一些简单的 C++ (或任何其他)脚本来加载图像并将其转换为asm源。 ..这是我几年前在 NASM 中写的一些古老的
320x200x256 colors
打印库(直接使用 EGA / VGA 字体):;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;GFX mode 13h print librrary ver:1.0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;txti init font adress
;char cx=color,al=ASCII,scr:di<=al ;cl=ch => no background
;print scr:di <= ds:si ,cx=color cl=ch => no background
;printl scr:di text after call ,cx=color ...
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
txti: pusha ;init font adress
push es
mov ax,1130h ; VGA BIOS - font info
mov bh,3 ; font 8 x 8 pixels
int 10h ; ES:BP returns font address
mov [cs:fonts],es ;get font adr
mov [cs:fonto],bp
pop es
popa
ret
fonts dw 0 ; font address for printing ...
fonto dw 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
char: pusha ;cx=color,al=ASCII,scr:di<=al ;cl=ch => no background
push ds
push es
push word 0A000h
pop es
sub ah,ah
shl ax,3
mov ds,[cs:fonts]
mov si,[cs:fonto]
add si,ax
mov dh,8
.char0: mov dl,8
lodsb
mov ah,al
.char1: mov al,cl
rcl ah,1
jc .char2
mov al,ch
.char2: cmp cl,ch
jz .char3
mov [es:di],al
.char3: inc di
dec dl
jnz .char1
add di,320-8
dec dh
jnz .char0
pop es
pop ds
popa
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
print: pusha ;scr:di <= ds:si ,cx=color cl=ch => no background
.l0: lodsb
or al,al
jz .esc
call char
add di,8
jmp short .l0
.esc: popa
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
printl: mov [cs:.dat],si ;scr:di text after call ,cx=color ...
pop si
push ax
push di
push ds
push cs
pop ds
.l0: lodsb
or al,al
jz .esc
call char
add di,8
jmp short .l0
.esc: pop ds
pop di
pop ax
push si
add di,9*320
mov si,[cs:.dat]
ret
.dat: dw 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; end. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
因此,要使用它,程序应类似于:
start:
call txti ; just once at program startup
mov di,50+320*10
mov cx,127
call printl
db 'SPEKTRA software & hardware',0
mov di,50+320*30
mov cx,127
call printl
db 'print test',0
通过设置
print
来使用ds,si
,以便它指向以null终止的字符串。正如您所看到的,printl
不需要使用它,因为它使用直接位于printl
调用之后的字符串,并且程序在它之后继续执行...这样,您就不需要指针设置指令或任何其他标签...颜色在cl,ch
中是一种墨水,另一种是纸。如果是cl==ch
,那么将不会仅渲染墨水像素,而如果您在文本后面放置图像或gfx背景,则墨水像素将不可用...颜色值可能不可见。我从我的一款游戏中获得了颜色,该游戏设置了自己的调色板因此,如果看不到任何内容,请尝试设置其他cl,ch
(例如mov cx,0305h
),看看这个:打印非负整数值是将数字除以基数(10)并以相反的顺序将
remainder + '0'
打印为字符的问题...在
hex
中,甚至更容易,因为每个数字都对应于半字节<0-15>
,因此对于16位,您可以通过xlat
表或通过添加'0'
或'A'
来将最高4位转换为char,具体取决于值是否低于10
……因此,没有除法位shift / mask ...打印字符并将值左移4位以处理下一位...gfx模式下的btw通常更好用和用户友好,而不是打印数值,因为数字可以像进度条一样显示进度条,而不是更容易...折叠成单循环渲染H或V线...就像
REP STOSB
:) ... 关于assembly - 部件8086中的图形模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48648548/