基于ega位面,把我头都给弄大。哪位大虾能否分析该MASM宏汇编。

thunk123 2008-04-03 08:52:57
Stack segment para stack 'STACK'
db 512 dup(0)
Stack ends

SCREEN_WIDTH_IN_BYTES equ 80
DISPLAY_MEMORY_SEGMENT equ 0a000h
SC_INDEX equ 3c4h ;Sequence Controller Index register
MAP_MASK equ 2 ;index of Map Mask register
GC_INDEX equ 03ceh ;Graphics Controller Index reg
GRAPHICS_MODE equ 5 ;index of Graphics Mode reg
BIT_MASK equ 8 ;index of Bit Mask reg

Data segment para common 'DATA'
;
; Current location of "A" as it is animated across the screen.
;
CurrentX dw ?
CurrentY dw ?
RemainingLength dw ?
;
; Chunky bit-map image of a yellow "A" on a bright blue background
;
AImage label byte
dw 13, 13 ;width, height in pixels
db 000h, 000h, 000h, 000h, 000h, 000h, 000h
db 009h, 099h, 099h, 099h, 099h, 099h, 000h
db 009h, 099h, 099h, 099h, 099h, 099h, 000h
db 009h, 099h, 099h, 0e9h, 099h, 099h, 000h
db 009h, 099h, 09eh, 0eeh, 099h, 099h, 000h
db 009h, 099h, 0eeh, 09eh, 0e9h, 099h, 000h
db 009h, 09eh, 0e9h, 099h, 0eeh, 099h, 000h
db 009h, 09eh, 0eeh, 0eeh, 0eeh, 099h, 000h
db 009h, 09eh, 0e9h, 099h, 0eeh, 099h, 000h
db 009h, 09eh, 0e9h, 099h, 0eeh, 099h, 000h
db 009h, 099h, 099h, 099h, 099h, 099h, 000h
db 009h, 099h, 099h, 099h, 099h, 099h, 000h
db 000h, 000h, 000h, 000h, 000h, 000h, 000h
Data ends

Code segment para public 'CODE'
assume cs:Code, ds:Data
Start proc near
mov ax,Data
mov ds,ax
mov ax,12h
int 10h ;select video mode 10h (640x350)
;
; Prepare for animation.
;
mov [CurrentX],0
mov [CurrentY],200
mov [RemainingLength],600 ;move 600 times
;
; Animate, repeating RemainingLength times. It's unnecessary to erase
; the old image, since the one pixel of blank fringe around the image
; erases the part of the old image not overlapped by the new image.
;
AnimationLoop:
mov bx,[CurrentX]
mov cx,[CurrentY]
mov si,offset AImage
call DrawFromChunkyBitmap ;draw the "A" image
inc [CurrentX] ;move one pixel to the right

mov cx,0 ;delay so we don't move the
DelayLoop: ; image too fast; adjust as
; needed
loop DelayLoop

dec [RemainingLength]
jnz AnimationLoop
;
; Wait for a key before returning to text mode and ending.
;
mov ah,01h
int 21h
mov ax,03h
int 10h
mov ah,4ch
int 21h
Start endp
;
; Draw an image stored in a chunky-bit map into planar VGA/EGA memory
; at the specified location.
;
; Input:
; BX = X screen location at which to draw the upper left corner
; of the image
; CX = Y screen location at which to draw the upper left corner
; of the image
; DS:SI = pointer to chunky image to draw, as follows:
; word at 0: width of image, in pixels
; word at 2: height of image, in pixels
; byte at 4: msb/lsb = first & second chunky pixels,
; repeating for the remainder of the scan line
; of the image, then for all scan lines. Images
; with odd widths have an unused null nibble
; padding each scan line out to a byte width
;
; AX, BX, CX, DX, SI, DI, ES destroyed.
;
DrawFromChunkyBitmap proc near
cld
;
; Select write mode 2.
; 选择写方式2
mov dx,GC_INDEX
mov al,GRAPHICS_MODE
out dx,al
inc dx
mov al,02h
out dx,al
;
; Enable writes to all 4 planes.
;
mov dx,SC_INDEX ;选择时序寄存器
mov al,MAP_MASK
out dx,al ;选择映像屏蔽寄存器(选择那些位面有效)
inc dx
mov al,0fh
out dx,al ;位面全部有效
;
; Point ES:DI to the display memory byte in which the first pixel
; of the image goes, with AH set up as the bit mask to access that
; pixel within the addressed byte.
;
mov ax,SCREEN_WIDTH_IN_BYTES
mul cx ;offset of start of top scan line
mov di,ax
mov cl,bl
and cl,111b
mov ah,80h ;set AH to the bit mask for the
shr ah,cl ; initial pixel
shr bx,1
shr bx,1
shr bx,1 ;X in bytes
add di,bx ;offset of upper left byte of image
mov bx,DISPLAY_MEMORY_SEGMENT
mov es,bx ;ES:DI points to the byte at which the
; upper left of the image goes
;
; Get the width and height of the image.
;
mov cx,[si] ;get the width
inc si
inc si
mov bx,[si] ;get the height
inc si
inc si
mov dx,GC_INDEX ; 选择图像控制寄存器
mov al,BIT_MASK ; 选择位屏蔽寄存器
out dx,al ;leave the GC Index register pointing
inc dx ; to the Bit Mask register
RowLoop: ;行循环

push ax ;preserve the left column's bit mask
push cx ;preserve the width
push di ;preserve the destination offset

ColumnLoop: ;列循环
mov al,ah
out dx,al ;set the bit mask to draw this pixel 为要写的像素设置位掩码
mov al,es:[di] ;load the latches 装载锁存器
mov al,[si] ;get the next two chunky pixels
shr al,1 ;从此行开始到最后一行都不明白
shr al,1
shr al,1
shr al,1 ;move the first pixel into the lsb
stosb ;draw the first pixel
ror ah,1 ;move mask to next pixel position
jc CheckMorePixels ;is next pixel in the adjacent byte? 接下来的像素在相邻字节吗
dec di ;no

CheckMorePixels:
dec cx ;see if there are any more pixels
jz AdvanceToNextScanLine ; across in image
mov al,ah
out dx,al ;set the bit mask to draw this pixel
mov al,es:[di] ;load the latches
lodsb ;get the same two chunky pixels again
stosb ;draw the second of the two pixels
ror ah,1 ;move mask to next pixel position
jc CheckMorePixels2 ;is next pixel in the adjacent byte?
dec di ;no
CheckMorePixels2:
loop ColumnLoop ;see if there are any more pixels
jmp short CheckMoreScanLines
AdvanceToNextScanLine:
inc si ;advance to the start of the next

CheckMoreScanLines:
pop di ;get back the destination offset
pop cx ;get back the width
pop ax ;get back the left column's bit mask
add di,SCREEN_WIDTH_IN_BYTES
dec bx ;see if there are any more scan lines
jnz RowLoop ; in the image
ret
DrawFromChunkyBitmap endp
Code ends
end Start
各位帮帮忙啊
...全文
253 46 打赏 收藏 举报
写回复
46 条回复
切换为时间正序
请发表友善的回复…
发表回复
cnzdgs 2008-04-08
  • 打赏
  • 举报
回复
设置位屏蔽寄存器只需要一次输出,输出的字节中为1的那一位对应位面被选中,其它位面都屏蔽。
thunk123 2008-04-08
  • 打赏
  • 举报
回复
像素显示的位置这个问题解决了,堆栈处理不当
thunk123 2008-04-08
  • 打赏
  • 举报
回复
而且像素显示的位置也不对
thunk123 2008-04-08
  • 打赏
  • 举报
回复
啊,为什么,我按你所说的理解为:一个颜色,进行各位屏蔽后才写入位面,我的那个循环也是这个目的。我那理解错了!
cnzdgs 2008-04-08
  • 打赏
  • 举报
回复
你这是一个循环,把jmp point去掉就是一个点了。另外
ror al,1
jc done
这两行应该去掉。
thunk123 2008-04-08
  • 打赏
  • 举报
回复
.model small
vgaseg equ 0a000h
sequen_ctl equ 3c4h
graphi_ctl equ 3ceh
Onscreen_X equ 20
Onscreen_y equ 100
linelen equ 640/8
only_one_pixel equ 003h
.code
start:

mov ax,vgaseg ;ES段指向显存地址0a000h
mov es,ax
mov cx,0
mov dx,184Fh
mov bh,07
mov ax,600h
int 10h

;没有堆栈

mov ax, 12h
int 10h

mov ax,Onscreen_y
push ax
mov ax,Onscreen_X
push ax
call enable_write_mode_one
enable_write_mode_one proc
mov bp,sp
mov ax,[bp] ;取x
mov cl,3
shr bx,cl ;X0/8
mov ax,[bp+2]
mov cx,linelen
mul cx
add ax,bx ;该坐标所在内存字节
mov di,ax

;设置映象屏蔽寄存器
mov dx,sequen_ctl
mov al,2
out dx,al
inc dx
mov al,0fh ;四个位面全部充许写
out dx,al
;选择写方式2
mov dx,graphi_ctl
mov al,5
out dx,al
inc dx
mov al,2
out dx,al
;计算屏蔽码,并设置位屏蔽寄存器
point: dec dx
mov al,8
out dx,al
mov cx,[bp] ;取出X在一个位面上位置
and cl,7
mov al,80h
shr al,cl
inc dx
out dx,al
ror al,1
jc done
;写数据
mov ax,only_one_pixel ;取颜色值
mov ah,es:[di] ;读一次使屏蔽寄存器有效
mov es:[di],al ;写入显示存储器
mov ax,[bp]
inc ax
mov [bp],ax
jmp point

done:nop
jmp done

enable_write_mode_one endp
end start

从POINT开始我的目的是显示一个点,但结果是一条线
cnzdgs 2008-04-08
  • 打赏
  • 举报
回复
跟时钟周期没有关系。

写的时候有8个位面,每个位面中的1字节(只有低4位有效)对应1个像素值。
读的时候有4个位面,4个位面中的同一位对应1个像素值的4位数据。

建议你先做一个写单一像素的函数,可以在屏幕上任意位置画一个点,然后再练习用画点的方式贴图;写单一像素熟悉了之后,再做一个画横线函数,可以在屏幕上任意位置画任意长度的横线,然后再练习画矩形;然后再做一个读单一像素的函数;再做读一个读横线函数,再练习读矩形。到这基本就都掌握了,可以再熟悉其它操作模式。
thunk123 2008-04-08
  • 打赏
  • 举报
回复
是不是0~3位面相同位对应一个4位值
thunk123 2008-04-08
  • 打赏
  • 举报
回复


|--| ----------------------|
|1 | 0位面的1个字节 |
| | 从最高位开始 |
|--| 每个时钟周期移动一个BIT |
|
|--| |
| 1| 1位面的1个字节 |
| | 从最高位开始 |
|--| 每个时钟周期移动一个BIT |
| 四位颜色值
|
|--| |
| 2| 2位面的1个字节 |
| | 从最高位开始 |
|--| 每个时钟周期移动一个BIT |
|
|--| |
|3 | 3位面的1个字节 |
| | 从最高位开始 |
|--| 每个时钟周期移动一个BIT -------------|



迷糊了,怎么又成一个字节了啊
thunk123 2008-04-08
  • 打赏
  • 举报
回复
总之,我还是谢谢你这几天回复,的确我被VGA各种操作搞混了,还是专注的看另一本书吧!:-)
cnzdgs 2008-04-08
  • 打赏
  • 举报
回复
1、这种显示模式整个屏幕就是640*480个像素;
2、写一个点就是要选一个位面,如果是画线才需要循环切换位面。
thunk123 2008-04-08
  • 打赏
  • 举报
回复
我有两本VGA方面的电子版,说的都是很笼统,所以有时候分布清那是对的那是错的。。
1:你的意思是说一个页面有640*480个像素吗。
2:"余数是位面代号(将其保存到CL),把80H右移CL位",这只是单个位面吧,我的意思就是想使用XOR CL,1移动掩码位啊,就像我上面代码那样。
cnzdgs 2008-04-08
  • 打赏
  • 举报
回复
你现在理解的很混乱。
在写模式2下,A000段的每个字节对应的是8个像素,这8个像素各对应一个位面。在写像素之前要通过设置位屏蔽寄存器来控制选择其中1个位面,屏蔽其它7个位面。屏蔽寄存器中的8位二进制数中每1位对应一个位面,为1的位面有效,为0位面屏蔽。
当要写一个像素时,首先根据像素坐标(X,Y),先计算Y*640+X,这是总的像素序号,然后把Y*640+X除以8,商就是该像素在A000段的偏移量(将其保存到DI),余数是位面代号(将其保存到CL),把80H右移CL位,然后输出到位屏蔽寄存器,这样就选中了该像素对应的位面同时屏蔽了其它无关位面,然后把A000:DI的数据先读出一下,再把要写入的像素值写入,这样就完成了。
thunk123 2008-04-08
  • 打赏
  • 举报
回复
还有就是为什么要把X坐标除8,X不是已经是个字节(像素),还是它的这个像素概念是相对于位面???

假设颜色数值是003h(因为有8位,所以有8个像素),即二进制0000011。设x=1,那么x坐标求余为1,相反屏蔽了位6,那么剩下5位,我怎么办了,我通过循环也就是这个目的
cnzdgs 2008-04-07
  • 打赏
  • 举报
回复
我看你是离线状态。
你只要知道:在16色显示模式下,读一个像素是从4个位面各读一位数据;写一个像素是向1个位面写一字节数据(低4位有效)就可以了。
thunk123 2008-04-07
  • 打赏
  • 举报
回复
请问您能否在线聊天(WEB)。
thunk123 2008-04-07
  • 打赏
  • 举报
回复
看了一天的代码,还是没什么收获。一会儿又是4位一个像素,一会儿又一字节一个像素。现在到好彻底的混为一谈了!!
cnzdgs 2008-04-07
  • 打赏
  • 举报
回复
cnzdgs 2008-04-07
  • 打赏
  • 举报
回复
thunk123 2008-04-07
  • 打赏
  • 举报
回复
不知道是不是
CheckMoreScanLines:
pop di ;get back the destination offset
pop cx ;get back the width
pop ax ;get back the left column's bit mask
add di,SCREEN_WIDTH_IN_BYTES ;开始下一扫描线
加载更多回复(26)
相关推荐
发帖
汇编语言

2.1w+

社区成员

汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
帖子事件
创建了帖子
2008-04-03 08:52
社区公告
暂无公告