Animation 16位动画-入门
花了一段时间,但最终在16位图形中得到了平方1。 在这里,我清除屏幕并绘制单个像素:Animation 16位动画-入门,animation,assembly,nasm,machine-code,Animation,Assembly,Nasm,Machine Code,花了一段时间,但最终在16位图形中得到了平方1。 在这里,我清除屏幕并绘制单个像素: mov ax, 0a000h mov es, ax ; es - Extra Segment now points to the VGA location mov ax, 0013h int 10h xor al, al mov dx, 3c8h out dx, al inc dx mov al, 63 out dx, al out dx, al out dx, al mov ax, 0100
mov ax, 0a000h
mov es, ax ; es - Extra Segment now points to the VGA location
mov ax, 0013h
int 10h
xor al, al
mov dx, 3c8h
out dx, al
inc dx
mov al, 63
out dx, al
out dx, al
out dx, al
mov ax, 0100h
int 21h
mov ax, 4c00h
int 21h
; draw single pixel :)
mov ah, 0ch;
mov al, 03h ; color
mov cx, 70 ; x co-ordinate
mov dx, 70 ; y co-ordinate
; mov bh,1 ; page #
int 10h
times 510-($-$$) db 0 ; PadZeros:
dw 0xaa55 ; MagicNumber
第二步:如何让它移动
显然,这意味着交替擦拭屏幕,更新和绘制循环中的像素。当然,它会在屏幕上飞过,所以我猜你会访问内部时钟的毫秒,比较,然后在它大于某个常数时更新
刚刚开始组装。我确实知道如何使用标签来生成伪函数,所以假设我可能已经在示例中完成了
我从nasm编译为bin,然后在qemu中直接打开。注意我不使用链接器,因此不需要使用.text或任何其他.bss
只是尝试从原始二进制文件开始工作
如果有人对低级机器代码入门教程感兴趣,我还试图记录我在YouTube上学到的一切:
如果其他任何人也在尝试编写内核、他们自己的操作系统、编译器或了解汇编中16位游戏图形的更多信息,请随时加入KAOS项目并帮助创建一个100%视频记录的操作系统:
这是80x80正方形最原始的动画 它的工作原理如下:
现在我明白了,然后
int8
计时器中断实际上是BIOS提供的,所以我可以重写这个例子,用这个计时来显示差异(VSYNC与计时器动画)…嗯…我非常不愿意,因为计时器动画很烂(我的意思是,即使是VSYNC动画也必须使用计时器来弥补跳过的帧,但这对于简单的例子来说太复杂了,但是基于计时器的动画天生就很糟糕)。我最多会给它10分钟,看看我是否能让它工作
好的,INT 08h
基于定时器的版本(不要看你是否也容易因闪烁的图像而癫痫发作):
它有两个主要问题:
int 8
默认情况下,计时器在55毫秒内滴答作响,而大多数屏幕又是60赫兹,因此在60赫兹上需要16.6毫秒的滴答声才能平滑,更不用说刷新率更高了。现在,正方形每3-4个显示帧移动+1个像素这两个例子都非常粗糙,基本上只是说明“清除屏幕+在新位置绘图”确实可以使内容具有动画效果,而且这还不足以达到基本的质量 为了得到任何合理的结果,你需要使用更复杂的逻辑,但这在很大程度上取决于你在画什么、制作什么动画以及如何制作 VGA的一种通用方法是使用屏幕外缓冲区,并在绘图完成时将其复制到VRAM(将机器周期浪费在64k字节的复制上..今天听起来可能很可笑,但在1990年这是一件大事)
或者使用VGA控制寄存器设置一种非官方的“x模式”并以支持双/三缓冲方案的方式设置VGA内存布局,因此直接将新帧绘制到VRAM中,但绘制到隐藏部分,绘制完成后,切换VRAM的显示部分以显示新准备的内容。这有助于避免64k拷贝,但写入VRAM实际上相当缓慢,因此只有在像素透支很少的情况下才值得付出努力。当像素透支很多时,速度已经太慢了(不可能达到60FPS),并在普通RAM屏幕外绘制它,使它实际上更快,即使最后的64k拷贝到VRAM。如果我正确读取该源代码,它会将颜色索引0设置为全白色,然后等待一个键并退出(如果加载了一些DOS,它会退出)。在
之后的代码;绘制单像素
是不可访问的?(现在我明白了,它是引导扇区,所以int21h
是无效的,不知何故不会崩溃它,只要返回,然后你通过BIOS绘制像素…我明白了)为什么你要通过BIOS绘制像素?:-o..只需像mov al,3
mov es:[70*320+70],al
那样将其写入内存。关于yo
BITS 16
MOV ax,13h
INT 10h ; 320x200 256colour VGA mode
MOV ax,0a000h
MOV es,ax ; video RAM segment
XOR bx,bx ; square position = 0
MOV si,1 ; direction of movement
AnimateLoop:
CALL waitforRetrace ; destroys al, dx
; clear whole screen
XOR di,di
XOR eax,eax
MOV cx,320*200/4
REP STOSD
; draw 80x80 pixels square with color 3
MOV eax,0x03030303
MOV di,bx
MOV dx,80 ; height
drawSquareLoop:
MOV cx,80/4
REP STOSD ; draw 80 pixels (single line)
ADD di,320-80 ; next line address
DEC dx
JNZ drawSquareLoop
; move it left/right
ADD bx,si ; move it first
CMP bx,240
JB AnimateLoop ; 0..239 are OK
; too far on either side, reverse the movement
NEG si
ADD bx,si ; fix position to valid range
JMP AnimateLoop
waitforRetrace:
MOV dx,03dah
waitforRetraceEnd:
IN al,dx
AND al,08h
JNZ waitforRetraceEnd
waitforRetraceStart:
IN al,dx
AND al,08h
JZ waitforRetraceStart
RET
times 510-($-$$) db 0 ; PadZeros:
dw 0xaa55 ; MagicNumber
BITS 16
MOV ax,13h
INT 10h
XOR ax,ax
; ds = 0 segment (dangerous, don't do this at home)
MOV ds,ax
MOV ax,0a000h
MOV es,ax ; video RAM segment
AnimateLoop:
; clear whole screen
XOR di,di
XOR eax,eax
MOV cx,320*200/4
REP STOSD
; draw square with color 3
MOV eax,0x03030303
; fetch position from BIOS timer-tick value
; (ticking every 55ms by default)
MOVZX di,byte [0x046C] ; di = 0..255 from [0:046C]
MOV dx,80 ; height
drawSquareLoop:
MOV cx,80/4
REP STOSD
ADD di,320-80 ; next line address
DEC dx
JNZ drawSquareLoop
JMP AnimateLoop
times 510-($-$$) db 0 ; PadZeros:
dw 0xaa55 ; MagicNumber