⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 final.asm

📁 这个程序实现的功能是在300*200 8位显示模式下读取图片并通过改变其显示位置从而实现汇编下的动画的功能
💻 ASM
字号:
extrn Openfile:far,CloseFile:far,ReadFile:far
extrn readdata:far
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
delay	macro 	times;;;;;画面滞留,减慢移动速度;times为外循环次数,用于控制移动速度
	local d11,d12
	     mov dx,times
d11:         mov cx,0ffffh  
d12:         loop d12
             dec   dx
             jnz   d11	
endm
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
RestoreGraphics macro
mov ah, 00h
int 16h
mov ah, 00h
mov al,  00h
int 10h
endm
;////////////////////////////////////////
display macro ImageSrc
	lea dx,ImageSrc;用于选择图片,写成宏
	push si		;后面用到的[bp+8]
	push di		;后面的[bp+6]
	push dx		;后面的[bp+4]
	call bitmap
	cmp Eflag,0
	jnz exitDoszz 	
endm
;///////////////////////////////////////
Stack   Segment
        Stk          db    65535    dup(?)
Stack   Ends
Data    Segment	common
        ImageBuffer  	db    65078    dup(?)
	ImageSrc1     	db 'test.bmp',0
	ImageSrc2	db 'test2.bmp',0
	ImageSrc3	db 'test3.bmp',0
	ImageSrc4	db 'test4.bmp',0
	ImageSrc5	db 'test5.bmp',0
	Eflag        	dw    0
	OpenErrorMsg 	db '***open error***',0dh,0ah
	readmsg      	db '***read error***',0dh,0ah
	Not256Color  	db    'Not a 256 color bitmap',24h
	handle       	dw    ?
Data    Ends
;;;;;;;;;;;;;;;;\;\\\\\\\\\\\\\\\\\\\\\

Code     Segment				;50th row
         Assume cs:Code,ds:Data,ss:Stack
main proc far
Start:
        mov ax,Data
	mov ds,ax
	xor ax,ax	

	mov ax,-600
loop1:
	add ax,8
	cmp ax,310
	jg next1 
	mov di,ax
	mov si,40
	display ImageSrc1	;宏调用
	;delay 20
	jmp loop1
next1:
	mov ax,-64
	mov bx,-64
loop2:
	add ax,4
	cmp ax,315
	jg next2
	add bx,2
	cmp bx,195
	jg next2 
	mov di,ax
	mov si,bx
	display ImageSrc2
	;delay 40
	jmp loop2
next2:
	mov ax,-64
	mov bx,200	
loop3:
	add ax,4
	cmp ax,315
	jg next3
	sub bx,2
	cmp bx,0
	jng next3 
	mov di,ax
	mov si,bx
	display ImageSrc3
	;delay 40
	jmp loop3
exitDoszz:
	jmp exitDos
next3:
	mov ax,320
	mov bx,-64	
loop4:
	sub ax,4
	cmp ax,-60
	jng next4 
	add bx,2
	cmp bx,195
	jg next4 
	mov di,ax
	mov si,bx
	display ImageSrc4
	;delay 40
	jmp loop4
next4:
	mov ax,320
	mov bx,200	
loop5:
	sub ax,4
	cmp ax,-60
	jng exitDos
	sub bx,2
	cmp bx,-60
	jng exitDos 
	mov di,ax
	mov si,bx
	display ImageSrc5
	;delay 40
	jmp loop5

exitDos:

	RestoreGraphics;;;;恢复原来的显示模式
	call far ptr readdata
	RestoreGraphics
	mov ax,4c00h
	int 21h	
main endp

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
bitmap proc near

        push bp	;bp用于作为寻找将会保存在堆栈中的BMP头信息的基址
	mov bp,sp
	 sub sp,20
push ax
	 push bx
	 push cx
	 push dx
	 push si
	 push di
	 push es
	;sub sp,20	;在堆栈中预留20 Bytes的空间用于保存将用到的BMP头信息	
	mov dx,[bp+4]	;ImageSrc 地址
	call far ptr OpenFile
	cmp Eflag,0
	jnz exitz	;打开出错,退出		;;81th row
openOk:
	;;;Read  first 4 byte of the file in order to get the file size!!!              
        mov dx,offset ImageBuffer    ;图片缓冲区        
        mov cx,4     ;设置将要读取的字节长度            
        call far ptr ReadFile
	cmp Eflag,0
	jz next	;读取出错,退出	
;;//////89th row
exitz:
	mov ax,01	;设置退出标志
	mov Eflag,ax
         pop es
	 pop di
	 pop si
	 pop dx
	 pop cx
	 pop bx
	 pop ax
         add sp,20
	 pop bp
	 ret 6
        ;ret		;退出
;;//////
next:
	call far ptr CloseFile

	;;;Read The entire bitmap file to memory/////////////////////////////
	mov si,2  	;
	mov cx,[si]       ;Save the bitmap file entire size to CX Register  ;;;100th row

	mov dx,[bp+4]     ;取得 ImageSrc 地址
	call far ptr OpenFile	;再次打开文件
	cmp Eflag,0
	jnz exitzz	;打开出错,退出

	call far ptr ReadFile	;读取的文件长度已经保存在CX中了,长度为整个文件长
	cmp Eflag,0
	jnz exitzz	;读取出错,退出	
 	call far ptr CloseFile	;关闭文件

  	;Save Information to local variable
	;把相关BMP头文件信息保存到变量中(堆栈中)之前已经预留20个字节的空间;
	mov si,012h   
        mov ax,[si]       
	mov [bp-2],ax     ;Save BmpWidth 
	mov [bp-4],ax     ;Save BmpOnScreenWidth 在屏幕显示的宽度
	mov [bp-6],ax     ;Save BytePerRow   每行显示的宽度
        mov cl,4          
	div cl            ;图像长度除以4

	cmp ah,0       	  ;余数保存在ah 
	jz  NoDwAA        ;No Dword align adjust  余数为零,说明是双字对齐的
	mov cl,4         	
	sub cl,ah    	  ;4-余数,即为还差的使它能够双字对齐的长度
	add [bp-6],cl     ;保存到堆栈的bp-6位置(校正长度)
                
NoDwAA:
         mov cx,0 
	 mov [bp-8],cx     ;Save LeftCutWidth,Default = 0 
			   ;图片隐藏在显示器屏幕左边的长度
	 mov si,016h   
	 mov ax,[si]     
	 mov [bp-10],ax    ;Save BmpHeight 图片高度

	 mov [bp-12],ax    ;Save BmpOnScreenHeight 图片在屏幕中的显示高度

         mov si,01ch     
	 mov ax,[si]    
	 mov [bp-14],ax    ;Save BitPerPixel 图片每像素的比特数

	 mov si,0eh       
	 mov ax,[si]       ;Save bmpfileheader length BMP文件头长度
 
	 add ax,14        
	 mov [bp-16],ax    ;Save PaletteOffset 调色板偏移位置

         mov si,0ah       
	 mov ax,[si]     
	 mov [bp-18],ax    ;Save ImgDataOffset 图像数据偏移位置
 
         mov [bp-20],word ptr 0     ;Save RowOffset 行偏移量


	;;;; Save the value to Local variable局部变量
	jmp CoorDinateX
exitzz:
	mov ax,01	;设置退出标志
	mov Eflag,ax
         pop es
	 pop di
	 pop si
	 pop dx
	 pop cx
	 pop bx
	 pop ax
         add sp,20
	 pop bp
	 ret 6

CoordinateX:     
	 mov ax,[bp+6]     ;X coordinate 显示起点的X坐标
	 push ax
	 and ah,80	;如果ah为FFFF则说明X为负数,相与的结果就不为0
	 pop ax
	 jz  PositiveX     ;If X coordinate>=0,jump,正数则跳
	 mov ax,[bp+6]	;取得初始设置的X坐标

	 push ax
	 not ax
	 inc ax		;取反加一,求得|X|的值
	 mov [bp-8],ax     ;Save LeftCutWidth 这个值即为隐藏在屏幕左边的长度
	 pop ax

	 add ax,[bp-2]     ;X 坐标加上BmpWidth图像宽度,即图像最右边缘的显示位置
	 jnc exitzz        ;Exit if X coordinate add BmpWidth < 0
		;负数与图像宽度相加而不产生进位,说明图像最右边缘的显示位置
		;也不能显示出来,此时整个图像隐藏在屏幕左边
		;
	 jz exitzz         ;Exit if X coordinate add BmpWidth = 0
		;道理同上类似
	 push ax
	 mov cx,320
	 sub cx,ax	;屏幕宽度减去图像最右边缘的显示位置,即为实际显示出来的
			;相对于屏幕左边缘的位置RowOffset
	 mov [bp-20],cx    ;Save RowOffset 保存

         add ax,[bp-8]    ; 图像最右边缘的显示位置+左边裁剪的宽度
	 mov [bp-4],ax     ;Save BmpOnScreenWidth + LeftCutWidth
	 pop ax

	 mov cx,320
	 cmp cx,ax
	 jnc NoWOverf      ;No Width Overflow图像最右边缘的显示位置超出了屏幕右边缘?
	 mov ax,[bp-8]
	 add ax,320	   ;LeftCutWidth+屏幕宽 :如果超出屏幕右边缘,
			   ;就用320代替图像显示的图像右边缘
	 mov [bp-4],ax     ;Save BmpOnScreenWidth = 320 + LeftCutWidth

	 mov ax,0
	 mov [bp-20],ax	   ;Save RowOffset 行偏移量

NoWOverf: 	;;如果未超出屏幕右边缘
         mov ax,0
         mov [bp+6],ax	;实际显示时的X坐标位置为屏幕左边缘

	 jmp CoordinateY

PositiveX:
         cmp ax,320	;显示的起点的X坐标-320
	 jnc exitzz	;后如果结果非负,说明图像将会完全隐藏在屏幕右边
         mov cx,320
	 sub cx,[bp-2]	;320-BmpWidth图像宽度,图像显示实际长度
	 mov [bp-20],cx ;保存

	 add ax,[bp-2]	;BmpWidth+显示的起点的X坐标,即为图像最右边缘的显示位置
	 mov cx,320	;
	 cmp cx,ax	;是否超过320?
	 jnc CoordinateY;没有超出则跳

	 mov ax,320	;超出了,就用320代替图像最右边缘的显示位置
	 sub ax,[bp+6]	;减去x坐标位置,即为图像左边缘的显示位置
	 mov [bp-4],ax  ;Save OnScreenWidth保存

	 mov cx,320
	 sub cx,ax	;320-x坐标位置,即为图像左边缘与屏幕左边的距离RowOffset
	 mov [bp-20],cx    ;SaveRowOffset

CoordinateY:
         mov ax,[bp+8]     ;Y 坐标
         push ax
	 and ah,80	   ;如果ah为FFFF则说明Y为负数,相与的结果就不为0
	 pop ax			
	 jz PositiveY
		;Y 坐标为负
	 add ax,[bp-10]		;BmpHeight图像高度+Y 坐标
	 jnc exitzz1		;
	 jz exitzz1		;结果<=0则图像完全在屏幕以上

	 mov [bp-10],ax    ;Save BmpHeight
	 mov [bp-12],ax    ;Save OnScreenHeight

	 mov cx,0
         mov [bp+8],cx	   ;Y的实际显示起始位置为0

	 mov cx,200
         cmp cx,ax	   ;OnScreenHeight>200?如果大于说明溢出到屏幕下方
	 jnc SetInt10      ;No Height Overflow
	 mov cx,200	   ;溢出,OnScreenHeight设置为200,实际能显示的高度
	 mov [bp-12],cx
NoHOverf:        
	 jmp SetInt10
exitzz1:
	mov ax,01	;设置退出标志
	mov Eflag,ax
         pop es
	 pop di
	 pop si
	 pop dx
	 pop cx
	 pop bx
	 pop ax
         add sp,20
	 pop bp
	 ret 6
PositiveY:	;Y坐标为正
         cmp ax,200	;Y坐标>=200,说明图像完全在屏幕下方
	 jnc exitzz1

	 add ax,[bp-10]	;取得BmpHeight
	 mov cx,200	
	 cmp cx,ax	;BmpHeight是否大于200
	 jnc SetInt10	;不大于则跳

	 mov ax,200	;大于则让
	 sub ax,[bp+8]	;200-Y坐标 作为OnScreenHeight实际能显示的高度
	 mov [bp-12],ax

	;;;;;;;;;Set the Palette register and copy image data to video buffer which 
		;address start at A000:0000.

SetInt10:
        mov ax,013h     
        int 10h          ;Set Video Mode to 13h设置到【320*200  256色】的显示模式
        mov dx,03c6h	;写图形控制寄存器接口,水平位移寄存器
        mov ax,0ffh	;写入的数据是0ffh,D0 ~ D3为水平左移点数,D4~D7不使用
        out dx,ax
	mov si,[bp-16]	;调色板偏移地址
	mov di,0	;

	mov cx,256	;循环次数	
	call SetPalette ;设置调色板	;280th row
	call Showbmp	;显示
	

exit:
	delay 200h
         pop es
	 pop di
	 pop si
	 pop dx
	 pop cx
	 pop bx
	 pop ax
         add sp,20
	 pop bp
	 ret 6
bitmap endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SetPalette proc near  
SetP:    
         mov dx,03c8h		;颜色查找表写寄存器,用于存放颜色查找表单元地址
				;
         mov ax,di		;di=0 颜色查找表单元地址
         out dx,al		;写入

         mov dx,03c9h		;颜色查找表数据寄存器,用于存放写入或读出
				;颜色查找表某单元的数据
	;;;;;;;;;;三个写3C9H端口命令即可修改颜色查找表的一组彩色值,
	;;;;;;;;;;每写3个字节后,写序号寄存器中的内容自动+1
         mov al,byte ptr[si+2]	;调色板偏移地址+2
	 push bx
         mov bl,63		
         mul bl			;;[si+2]*63

         mov bl,0ffh
         div bl			;;([si+2]*63)/0ffh

	 pop bx
         out dx,al

	 mov al,byte ptr[si+1]	;调色板偏移地址+1
	 push bx
         mov bl,63
         mul bl
         mov bl,0ffh
         div bl
	 pop bx
         out dx,al

	 mov al,byte ptr[si]	;调色板偏移地址
	 push bx
         mov bl,63
         mul bl
         mov bl,0ffh
         div bl
	 pop bx
         out dx,al

      	 add si,4
	 inc di
	 loop SetP
	ret
SetPalette endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Showbmp proc near
         mov ax,0a000h    ;Video memory start address   
	 mov es,ax	  ;

	 mov ax,[bp+8]	  ;Y坐标显示起点
         mov cx,320
	 mul cx		  ;Y坐标显示起点*320,即为起点开始以下的屏幕像素

	 add ax,[bp+6]	  ;低位结果AX加上X坐标显示起点
	 mov di,ax	  ;传给di
vertical:	;垂直移动
         cmp word ptr[bp-12],0	;if bitmapHeightOnScreen==0,display finished ,exit
	 ;jz exit
	 jz return

	 dec word ptr[bp-10]	;bitmapHeight--
	 dec word ptr[bp-12]	;bitmapHeightOnScreen--
	 mov ax,[bp-10]		;BmpHeight

	 mul word ptr[bp-6]	;bitPerRow*BmpHeight,即为已经显示的像素块
	 mov bx,ax
	 add bx,[bp-18]		;bx+imagDataOffset图像数据偏移

	 mov si,0
	 add si,[bp-8]		;leftCutWidth
horizon:	;水平移动
         cmp si,word ptr[bp-4]	;bitmapWidthOnSreen=leftCutWidth?if so, the end of a row
	 jz horizonend
	 mov al,[bx][si]	;已经显示的像素块+图像数据偏移+leftCutWidth
	 mov es:[di],al
	 inc si
	 inc di
	 jmp horizon
horizonEnd:	;一行的显示已经结束,跳到下一行的开头
         add di,[bp-20]		;di+rowOffset
	 jmp Vertical
return:
	ret
Showbmp endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
code ends
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	end Start

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -