汇编代码存档

本文包含多个汇编语言编程项目实例,涉及字符显示、数学运算、字符串处理等内容。通过具体案例展示汇编语言的应用技巧,如字符雨效果、迷宫求解等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

程序设计项目一

data segment

    dw

data ends

end

要求:

只在定义的数据段'?'中加入相关的内容,使得上面的程序可以在屏幕中间显示一个绿色的字符'A'。

 

data segment
	dw 00b8h, 8eb8h, 0bec0h, 0140h, 02b4h, 61b0h, 8926h, 0b804h, 4c00h, 21cdh
data ends
end


程序设计项目二

对加密的字符串进行解密。

要求:

(1)加密的字符串放在Cryptography段。

(2)解密方法:将Cryptography段的每个字符的ASCII值减去1。

(3)用汇编语言实现程序,将Cryptography段的数据按照解密方法进行解密,将解密后的数据放在PlainText段,然后再把解密之后的字符串以白底蓝字方式显示到屏幕中间。

(4)密文和明文的数据段定义如下:

Cryptography segment

        db 'tqsfbe!zpvs!xjoht'

        db '!!cf!zpvs!nbtufs!'

Cryptography ends

 

PlainText segment

        db 2*17 dup (' ')

PlainText ends

assume cs:code, ds:code

Cryptography segment
        db 'tqsfbe!zpvs!xjoht'
        db '!!cf!zpvs!nbtufs!'
Cryptography ends

PlainText segment
        db 2*17 dup (' ')
PlainText ends

code segment
s:
	mov ax, Cryptography
	mov ds, ax
	mov ax, PlainText
	mov es, ax

	mov bx, 0

	mov cx, 34
s0:						;解码
	mov al, ds:[bx]
	sub al, 1
	mov es:[bx], al
	inc bx
	loop s0			

	mov ax, 0b800h
	mov ds, ax
	mov bx, 0140h	;指向显存内容
	mov bp, 0 		;指向PlainText

	mov cx, 34
s1:					;将揭秘内容输出到显存内存段
	mov al, es:[bp]
	mov ah, 01110001b
	mov ds:[bx], ax
	inc bp
	add bx, 2
	loop s1

	mov ax, 4c00h
	int 21h
code ends
end s

程序设计项目三

   

加、减、除三则运算。

 

要求:

(1)读取字符串的内容,判断第四个字符是'+'、'-'或'/',然后按照相应的符号进行运算,并把运算结果转换为字符串存放在等号后面,最后把算式显示到屏幕中间,白底蓝字。

(2)注意数字字符的ASCII与数字的对应关系,数字的数值加30H为这个数字的字符所对应的ASCII。

(3)数据段定义如下:

Calculate segment

        db '1. 3/1=         '

        db '2. 5+3=         '

        db '3. 9-3=         '

        db '4. 4+5=         '

Calculate ends

assume cs:code, ds:code

Calculate segment
        db '1. 3/1=         '
        db '2. 5+3=         '
        db '3. 9-3=         '
        db '4. 4+5=         '
Calculate ends

stack segment
	dw 0,0,0,0,0,0,0,0
stack ends

code segment
s:
	mov ax, Calculate
	mov ds, ax
	mov ax, 0b800h
	mov es, ax
	mov ax, stack
	mov ss, ax

	mov bx, 0 		;数据基址
	mov bp, 0140h 	;显存基址
	mov di, 0 		;数据变址
	mov si, 0 		;显存变址

	mov cx, 4
s0:	
	push cx
	mov al, ds:[bx + 3]
	sub al, 30h
	mov dl, ds:[bx + 5]
	sub dl, 30h			;首先获得两个操作数
	mov ah, 0
	mov dh, 0 			;高位清零

	mov cl, ds:[bx + 4]	;获得操作符
	mov ch, 0

	sub cx, 47			;判断是否是除法
	jcxz divop
	add cx, 47

	sub cx, 43			;判断是否是加法
	jcxz addop
	add cx, 43

	sub cx, 45			;判断是否是减法
	jcxz subop
	add cx, 45

divop:
	div dl
	add ax, 30h
	mov ds:[bx + 7], al
	jmp opend
addop:
	add ax, dx
	add ax, 30h
	mov ds:[bx + 7], al
	jmp opend
subop:
	sub ax, dx
	add ax, 30h
	mov ds:[bx + 7], al
	jmp opend

opend:
	add bx, 16
	pop cx
	loop s0

	mov cx, 4
	mov bx, 0
s1:
	push cx
	mov si, 0
	mov di, 0
	mov cx, 16
s2:
	mov al, ds:[bx + di]
	mov ah, 01110001b
	mov es:[bp + si], ax
	inc di
	add si, 2
	loop s2

	add bp, 0a0h
	add bx, 16
	pop cx
	loop s1
	
	mov ax, 4c00h
	int 21h
code ends

end s

程序设计项目四

 

编程计算x(x>2)的y(y>2)次方。使用add指令实现。

另,若学到第10章,使用两种方式实现:

(1)只使用add指令实现;

(2)只使用mul指令实现;

并将计算式显示在屏幕中央



只用add:

assume cs:code

stack segment
	dw 0,0,0,0,0,0,0,0
stack ends

data segment
	dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
data ends

code segment
s:
	mov ax, stack
	mov ss, ax
	mov sp, 10h

	mov ax, data
	mov ds, ax 		;ds指向数据段
	mov ax, 0b800h
	mov es, ax 		;es指向显存段

	mov bx, 0 		;ds:[bx]
	mov bp, 0140h	;es:[bp]

	mov ax, 10
	mov dx, 3		;4^3

	mov cx, dx
	mov di, ax
	mov si, ax
	sub cx, 1
	sub di, 1
s0:
	push cx
	mov cx, di
s1:
	add ax, si
	loop s1
	mov si, ax
	pop cx
	loop s0			;计算结果保存在ax当中

	mov si, ax

	mov ax, 10 		;打印尾数
	call printres

	add bp, 0a0h
	mov al, 5eh
	mov ah, 01110001b
	mov es:[bp], ax	

	mov ax, 3 		;打印阶码
	call printres

	add bp, 0a0h
	mov cx, 5
	mov di, 0
s2:
	mov al, 2dh
	mov ah, 01110001b
	mov es:[bp + di], ax
	add di, 2
	loop s2

	mov ax, si 		;恢复结果,打印结果
	call printres

	mov ax, 4c00h
	int 21h

printres:
	add bp, 0a0h
	mov bx, 0 		;用bx来计算要打印的数字有几位
beg:
	mov dx, 10 		;每次除以10,求余数
	mov dh, 0
	div dl
	mov dl, ah
	mov dh, 01110001b
	push dx 		;保存余数
	inc bx
	mov cl, al
	mov ch, 0
	jcxz print 		;如果商是0的话,说明这是最高位数字了

	mov ah, 0 		
	jmp beg
print:
	mov cx, bx
	mov di, 0
s3:
	pop ax
	add ax, 30h
	mov es:[bp + di], ax
	add di, 2
	loop s3
	ret
code ends

end s
只用mul:
assume cs:code
code segment
s:
	mov ax, 0b800h
	mov es, ax
	mov bp, 0140h

	mov ax, 10
	mov dx, 3
	mov cx, dx
	sub cx, 1
	mov si, ax
s0:
	mul si
	loop s0

	mov si, ax  	;先将其结果保存起来
	
	mov ax, 10 		;打印尾数
	call printres

	add bp, 0a0h 	;打印^符号
	mov al, 5eh
	mov ah, 01110001b
	mov es:[bp], ax

	mov ax, 3 		;打印阶码
	call printres

	add bp, 0a0h 	;打印-----
	mov cx, 5
	mov di, 0
s1:
	mov al, 2dh
	mov ah, 01110001b
	mov es:[bp + di], ax
	add di, 2
	loop s1

	mov ax, si 		;从si恢复结果后再将其打印
	call printres

	mov ax, 4c00h
	int 21h

printres:
	add bp, 0a0h
	mov bx, 0 		;用bx来计算要打印的数字有几位
beg:
	mov dx, 10 		;每次除以10,求余数
	mov dh, 0
	div dl
	mov dl, ah
	mov dh, 01110001b
	push dx 		;保存余数
	inc bx
	mov cl, al
	mov ch, 0
	jcxz print 		;如果商是0的话,说明这是最高位数字了

	mov ah, 0 		
	jmp beg
print:
	mov cx, bx
	mov di, 0
s2:
	pop ax
	add ax, 30h
	mov es:[bp + di], ax
	add di, 2
	loop s2
	ret
code ends
end s

程序设计项目五

 

定义一个数据段如下:

data segment

    db 'h12E332l@L#O*&^!88nI@cE$%%$T1O m33E44E55t y77O88u!()'

    db '?'

data ends

注意:第一行字符串为待处理的数据,'?'为字符串结束符号。

 

设计程序完成如下操作:

(1)去掉除字母、空格、'!'之外的字符;

(2) 通过内存间的数据交换,将数据段中的字符串修改为'Hello!Nice tomeet you!';

(3)在屏幕正中打印处理好后的数据。

assume cs:code
data segment
    db 'i$5t^$^89 w@a7s 4%6t89609he——+ b{e};s,/t ,o"f ti]]m12e*s+!i^t &*(w()a#s 12t~h$e wo%r&s(t o*f(()) t+-i**m/es'
    db '?'
data ends

code segment
start:
	mov ax, data
	mov ds, ax
	mov ax, 0b800h
	mov es, ax
	mov bx, 0
	mov bp, 140h 		;ds:[bx], es:[bp]
	mov si, 0
	mov cx, 1 		;cx=1代表需要转换成大写
mainLoop:
	mov al, [bx]
	mov ah, 0
	cmp ax, '?'
	je break

	cmp ax, '!'
	je reset 		;如果是!,需要重新将cx置为1
	cmp ax, ' '
	je moveData

	cmp ax, 'A'
	jb clearData
	cmp ax, 'Z'
	ja judgeSmall
	jcxz toSmall
	jmp next
toSmall:
	add ax, 20h
next:
	mov cx, 0
	jmp moveData
judgeSmall:
	cmp ax, 'a'
	jb clearData
	cmp ax, 'z'
	ja clearData
	jcxz no
	sub ax, 20h
	mov cx, 0
no:	jmp moveData

	inc bx
	jmp mainLoop
break:
	mov ax, 4c00h
	int 21h

reset:
	mov cx, 1
	jmp moveData
moveData:
	mov byte ptr [bx], 0
	mov byte ptr ds:[si], al
	mov ah, 01110001b
	call print
	inc bx
	inc si
	jmp mainLoop
clearData:
	mov byte ptr [bx], 0
	inc bx
	jmp mainLoop
print:
	mov es:[bp], ax
	add bp, 2
	ret

code ends
end start

程序设计项目六

 

在屏幕中间显示:“中华”两个字。参看demo0.png示例。

 

提示:

通过字模提取工具,可以提取字的显示信息。

assume cs:code

data segment
	 DB  000H,000H,000H,000H,030H,000H,000H,03CH,000H,000H,038H,000H,000H,038H,000H,000H
	 DB  038H,000H,038H,038H,01CH,03FH,0FFH,0FCH,018H,038H,038H,018H,038H,038H,018H,038H
	 DB  038H,018H,038H,038H,018H,038H,038H,018H,038H,038H,03FH,0FFH,0F8H,038H,038H,038H
	 DB  000H,038H,000H,000H,038H,000H,000H,038H,000H,000H,038H,000H,000H,038H,000H,000H
	 DB  038H,000H,000H,038H,000H,000H,000H,000H 

	 DB  000H,000H,000H,000H,008H,000H,003H,08EH,000H,003H,0CCH,018H,007H,00CH,03CH,00EH
	 DB  00CH,0FCH,00FH,00DH,0E0H,01FH,00FH,080H,03FH,00EH,00CH,077H,03CH,00CH,067H,0ECH
	 DB  00EH,007H,08CH,00EH,007H,00FH,0FEH,007H,038H,000H,000H,03CH,000H,000H,038H,00CH
	 DB  0FFH,0FFH,0FEH,000H,038H,003H,000H,038H,000H,000H,038H,000H,000H,038H,000H,000H
	 DB  038H,000H,000H,038H,000H,000H,000H,000H
data ends

stack segment
	dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
stack ends

code segment
start:
	mov ax, data
	mov ds, ax
	mov bx, 0

	mov ax, stack
	mov ss, ax
	mov sp, 40h

	mov ax, 0b800h
	mov es, ax
	mov bp, 140h
	mov si, 0
	
	;打印“中”,注意点阵是24*24,所以应该是6个字节,但是最外层的循环还是24
	mov cx, 24
l1:
	push cx
	mov si, 0
	mov cx, 3
l2:
	push cx
	mov al, [bx]
	mov ah, 0
	mov di, 0
	call printByte ;打印ax中的一个字节内容,注意先化成二进制
	inc bx
	pop cx
	loop l2
	add bp, 0a0h ;换行
	pop cx
	loop l1

	;打印“华”
	mov bp, 140h
	mov cx, 24
l5:
	push cx
	mov si, 50
	mov cx, 3
l6:
	push cx
	mov al, [bx]
	mov ah, 0
	mov di, 0
	call printByte ;打印ax中的一个字节内容,注意先化成二进制
	inc bx
	pop cx
	loop l6
	add bp, 0a0h ;换行
	pop cx
	loop l5

	
	mov ax, 4c00h
	int 21h

printByte:
	mov cx, 8
l3:
	mov dl, 2
	div dl
	mov dl, al
	mov dh, 0
	mov al, ah
	mov ah, 0
	push ax
	mov ax, dx
	loop l3

	mov cx, 8 	;先解码成8位二进制数字
l4:
	pop ax
	call printBit
	loop l4
	ret

printBit:
	cmp ax, 1
	je ok
	mov dl, 20h
	mov dh, 71h
	jmp exit
ok:	mov dl, 2ah
	mov dh, 71h
exit:
	mov es:[bp + si], dx
	add si, 2
	ret
code ends
end start

程序设计项目七

 

在屏幕上显示一个兔子图形。参看demo1.gif示例。

assume cs:code

data segment
	db '.....*........*.......'
    db '....*..*.....*.*......'  
    db '.....*..*....*..*.....'  
    db '......*..*..*.*.*.....'  
    db '.....*.........*......'  
    db '...*.............*....'  
    db '..*...............*...'
    db '.*.................*..'  
    db '*...................*.'  
    db '*...................*.'  
    db '*.....*.......*.....*.'  
    db '*...................*.'  
    db '*...@.....U.....@...*.'  
    db '.*.................*..'  
    db '..**.............**...' ;15行22列
data ends

stack segment
	dw 0,0,0,0,0,0,0,0
stack ends

code segment
start:
	mov ax, data
	mov ds, ax
	mov bx, 0

	mov ax, 0b800h
	mov es, ax
	mov bp, 140h
	mov si, 0

	mov ax, stack
	mov ss, ax
	mov sp, 10h

	mov cx, 15 ;首先将图案绘制上去
l1:
	push cx
	mov cx, 22
	mov si, 0
	add bp, 0a0h
l2:
	mov al, [bx]
	mov ah, 00000111b
	mov es:[bp + si], ax
	add si, 2
	inc bx
	loop l2
	pop cx
	loop l1 	

blink:			;控制绘制的图案闪烁
	mov dh, 00000001b ;控制字符的属性,再循环过程中将会依次递增
	mov cx, 5 ;颜色5次变化一个轮回
l3:
	push cx
	mov bx, 1
	mov bp, 140h
	mov cx, 15
l4:
	push cx
	add bp, 0a0h
	mov si, 1
	mov cx, 22
l5:
	push cx
	mov es:[bp + si], dh
	add si, 2
	pop cx
	loop l5
	pop cx
	loop l4
	call sleep
	inc dh
	pop cx
	loop l3
	jmp blink

	mov ax, 4c00h
	int 21h

sleep:
 	mov cx,0fffh  ;注意:改变此cx值可改变延时的时间长短
s0:	push cx
    mov cx,000ffh
s1:	loop s1
    pop cx
    loop s0
    ret

code ends
end start

程序设计项目八

 

实现笑脸阶梯走效果。参看demo2.gif示例。

assume cs:code

stack segment
	dw 0,0,0,0,0,0,0,0
stack ends

code segment
start:
	mov ax, stack
	mov ss, ax
	mov sp, 10h

	mov ax, 0b800h
	mov ds, ax
	mov bx, 500h
	mov si, 0

	mov al, 2dh
	mov ah, 00000001b
	mov cx, 3 	;绘制阶梯
l1:
	push cx
	mov cx, 10
l2:
	mov [bx + si], ax
	add si, 2
	loop l2

	sub bx, 0a0h
	pop cx
	loop l1

run:
	mov bx, 460h
	mov si, 0
	mov al, 1
	mov ah, 00000001b
	mov cx, 3
l3:
	push cx
	mov cx, 10
l4:
	push cx
	push [bx + si]
	mov [bx + si], ax
	
	call sleep
	pop [bx + si]
	add si, 2
	pop cx
	loop l4

	sub bx, 0a0h
	pop cx
	loop l3
	jmp run

	mov ax, 4c00h
	int 21h

sleep:
 	mov cx,0fffh  ;注意:改变此cx值可改变延时的时间长短
s0:	push cx
    mov cx,000ffh
s1:	loop s1
    pop cx
    loop s0
    ret

code ends
end start

程序设计项目九

 

将ASCII码按顺序在屏幕上竖列显示。参看demo3.gif示例。

 

要求:

(1)逐个显示字符,相邻的两个字符之间显示要有时间间隔。

(2)字符颜色为绿色。

(3)每列显示20个字符,列间距为5个字符。显示完128个ASCII码,共需7列。

 

assume cs:code

stack segment
	dw 0,0,0,0,0,0,0,0
stack ends

code segment
start:
	mov ax, 0b800h
	mov ds, ax
	mov bx, 0
	mov si, 140h

	mov al, 0
	mov ah, 00000010b
	mov di, 0

	mov dl, 127
	mov dh, 00000010b
l1:
	add bx, 10
	mov si, 140h
	mov di, 0
l2:
	inc ax
	mov [bx + si], ax
	call sleep

	cmp ax, dx
	je exit 		;检测是否结束打印

	inc di
	cmp di, 20
	je l1 			;检测是否换列

	add si, 0a0h 	;换行继续打印
	jmp l2

exit:
	mov ax, 4c00h
	int 21h

sleep:
 	mov cx,0fffh  ;注意:改变此cx值可改变延时的时间长短
s0:	push cx
    mov cx,000ffh
s1:	loop s1
    pop cx
    loop s0
    ret

code ends
end start

程序设计项目十

 

在屏幕上斜着显示三个‘happy spring festival!’,字符串的颜色分别为蓝色、绿色和红色,并且各个字符串的颜色按规律变换。参看demo4.gif示例。

assume cs:code

stack segment
	dw 0,0,0,0,0,0,0,0
stack ends

data segment
	db 'happy spring festival!' 	;22
data ends

code segment
start:
	mov ax, stack
	mov ss, ax
	mov sp, 10h

	mov ax, 0b800h
	mov es, ax
	mov bp, 140h
	mov di, 10

	mov ax, data
	mov ds, ax
	mov bx, 0

	mov ah, 00000001b
	mov cx, 3
l1:
	push cx

	mov bx, 0
	add di, 6
	mov si, di
	mov bp, 140h

	mov cx, 22
l2:
	mov al, [bx]
	mov es:[bp + si], ax

	add bp, 0a0h
	add si, 4
	inc bx
	loop l2

	add ah, ah
	pop cx
	loop l1

blink:
	mov bp, 140h
	mov di, 11
	mov cx, 3
l3:
	push cx
	
	add di, 6
	mov si, di
	mov bp, 140h

	mov cx, 22
l4:
	mov ah, es:[bp + si]
	cmp ah, 00000100b
	je ok
	add ah, ah
	jmp exit
ok:	mov ah, 00000001b
exit:
	mov es:[bp + si], ah
	add bp, 0a0h
	add si, 4
	loop l4
	
	pop cx
	loop l3

	call sleep
	jmp blink

	mov ax, 4c00h
	int 21h

sleep:
 	mov cx,00ffh  ;注意:改变此cx值可改变延时的时间长短
s0:	push cx
    mov cx,00fffh
s1:	loop s1
    pop cx
    loop s0
    ret

code ends
end start

程序设计项目十一

   

动态画出一个棵七彩圣诞树。参看demo5.gif示例。

assume cs:code

direct segment
	dw 8, 160, -4, 6, 0, 4,	10, 160, -4, 10, 0, 4, 5, 160, 0, 4, 0, 4, 5, -160, 0, 10, 0, 4, 10, -160, -4, 6, 0, 4, 7, -160, -4
direct ends

data segment
	db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789ABCDE' ;40
data ends

stack segment
	dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
stack ends

code segment 			;第一行0    最后一行0f00h     一屏共有25行
start:
	mov ax, data
	mov ds, ax
	mov bx, 0

	mov ax, stack
	mov ss, ax
	mov sp, 20h

	mov ax, 0b800h
	mov es, ax
	mov bp, 0 		;bp从0行开始往下跟踪
	mov di, 0f00h	;di从0f00h开始向上跟踪
	
	mov cx, 25
rainLoop:
	push cx
	call sleep
	call rainDown
	call rainUp

	add bp, 0a0h
	sub di, 0a0h
	pop cx
	loop rainLoop

	;以下代码绘制圣诞树
	mov bp, 0
	mov si, 80
	mov al, 1
	mov ah, 00000001b
	mov es:[bp + si], ax

	mov ax, direct
	mov ds, ax
	mov al, 1
	mov ah, 01100001b
	mov bx, 0
	mov cx, 11
l1:
	push cx
	call drawLine
	pop cx
	loop l1

	mov ax, 4c00h
	int 21h

rainDown: 	;向下打印字符
	mov cx, 20
	mov bx, 0
	mov si, 0
downLoop:
	mov al, [bx]
	mov ah, 00000010b
	mov es:[bp + si], ax
	add si, 8
	add bx, 2
	loop downLoop
	ret

rainUp:		;向上打印字符
	mov cx, 20
	mov bx, 1
	mov si, 4

	mov ax, 0f00h
	sub ax, bp
	push bp
	mov bp, ax 		;以上4行代码将bp定位到最后一行,注意先将bp保存进栈
upLoop:
	mov al, [bx]
	mov ah, 00000010b
	mov es:[bp + si], ax
	add bx, 2
	add si, 8
	loop upLoop
	pop bp
	ret

drawLine: 	;每次从direct数据段提取出三个数据,分别是
	mov cx, [bx]
draw:
	push cx
	add bp, [bx + 2]
	add si, [bx + 4]
	inc ah
	cmp ah, 01100111b
	je ok
	jmp no
ok:	mov ah, 00000001b
no:	mov es:[bp + si], ax
	call sleep
	pop cx
	loop draw
	add bx, 6
	ret

sleep:
 	mov cx,00ffh  ;注意:改变此cx值可改变延时的时间长短
s0:	push cx
    mov cx,00fffh
s1:	loop s1
    pop cx
    loop s0
    ret

	
code ends
end start

程序设计项目十二

   

编写字符雨程序。参看demo6.gif示例。

 

提示:

(1)每列是一个单独的单元,在数据段中定义的数据要保证各列要显示的字符和开始显示的时机不一样。

(2)每一滴雨完全移出屏幕后,该雨滴所在列生成一个新的雨滴。

assume cs:code

data segment 	;这些数据可以写个c++程序随机生成。数据段每3个数字为一列的信息,分别是开头的行号、开头的字符ASSIC、以及长度
	dw 2240,10,10,2880,7,19,2880,1,11,3360,9,17,1760,9,19,2080,2,10,320,9,13,3840,6,12,2720,3,17,2080,3,17,2720,4,17,1760,3
	dw 20,3840,8,11,1440,1,18,320,7,13,2560,2,12,160,6,20,2880,2,15,2080,4,10,1440,8,12,0,6,11,3840,10,12,2240,8,17,1440,2,15
	dw 0,6,10,3040,3,14,1280,3,17,1760,7,14,2080,8,19,3040,8,20,2080,8,19,1280,1,19,1920,7,11,640,3,13,3360,10,15,3200,10,10
	dw 640,10,20,0,5,12,2560,1,16,1760,10,16,2720,3,20,320,9,12,2560,10,11,2240,10,12,960,8,12,160,4,13,1600,7,16,2720,8,12
	dw 2080,3,12,960,8,13,1920,1,19,480,10,17,2880,9,17,2400,2,13,2880,5,10,160,1,10,3840,7,17,2560,8,16,640,7,18,3360,3,19
	dw 3520,7,14,1760,5,11,2560,4,13,3840,3,20,0,8,17,1280,9,10,160,6,12,640,1,20,2080,7,17,1440,5,18,2240,9,16,480,2,13
	dw 2080,5,12,0,10,18,3200,10,16,3040,6,19,3200,3,16,0,8,18,160,1,16,800,6,15
data ends

stack segment
	dw 0,0,0,0,0,0,0,0
stack ends

code segment
start:
	mov ax, data
	mov ds, ax
	mov bx, 0 	;[bx]

	mov ax, stack
	mov ss, ax
	mov sp, 10h

	mov ax, 0b800h	;es:[bp + si]
	mov es, ax

rain:
	mov bx, 0
	mov si, 0
	mov cx, 80
loop0:
	push cx
	call draw_rain
	add si, 2
	add bx, 6
	pop cx
	loop loop0
	call sleep
	jmp rain

	mov ax, 4c00h
	int 21h

draw_rain: 				;该方法的作用是从数据段提取出该行的开头行号,开头字符,长度之后,将其存进di, ax, cx中。然后写进显存
	mov di, [bx] 		;提取行号
	mov ax, [bx + 4] 	;提取长度
	mov cx, ax

	mov dx, 160
	mul dx
	add ax, 0f00h
	cmp di, ax
	je ok
	jmp no
ok:	mov bp, 0f00h 					;检查雨滴是否已经落下
	mov byte ptr es:[bp + si], 0	;如果落下的话将di改为0,注意改为0之前要先擦除上一次的信息
	mov di, 0
	

no:	mov ax, [bx + 2]	;提取开头字符
	mov ah, 00000010b

	mov bp, di
loop1:
	mov es:[bp + si], ax
	sub bp, 160
	inc ax
	loop loop1

	mov byte ptr es:[bp + si], 0 	;将上一次的信息擦除

	add di, 160 	;更新开头的行号
	mov [bx], di
	ret

sleep:
 	mov cx,00ffh  ;注意:改变此cx值可改变延时的时间长短
s0:	push cx
    mov cx,005ffh
s1:	loop s1
    pop cx
    loop s0
    ret

code ends
end start


程序设计项目十三

   

编写左手逃生法则演示程序。参看demo7.gif示例。

   

提示:

(1)地图中只有三种元素:墙、通道、出口。设计地图时,要给不同的元素赋予不同的编码。

(2)什么情况下改变行进的方向。遇到这些情况后根据当前方向决定下一步方向变化的规律是什么。

(3)左手逃生法则简述:在一个有出入口,没有回路的迷宫中,一直保持左手贴着墙壁向前走,总能找到迷宫出口。

assume cs:code

data segment
	DB  0F0H,000H,000H,01FH,0FFH,0FFH,0F0H,000H,000H,01FH,0F0H,000H,000H,01FH,0FFH,0FFH
	DB  0F0H,000H,000H,01FH,0F0H,000H,000H,01FH,0FFH,0FFH,0F0H,000H,000H,01FH,0F1H,0FFH
	DB  0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,01FH,0F1H,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH
	DB  0FFH,01FH,0F1H,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,01FH,0F0H,000H,000H,003H
	DB  0FFH,0FFH,080H,000H,000H,01FH,0F0H,000H,000H,003H,0FFH,0FFH,080H,000H,000H,01FH
	DB  03FH,0FFH,0FFH,0E0H,000H,000H,00FH,0FFH,0FFH,0FFH,03FH,0FFH,0FFH,0E0H,000H,000H
	DB  00FH,0FFH,0FEH,000H,03FH,0FFH,0FFH,0FFH,000H,001H,0FFH,0FFH,0FCH,000H,000H,000H
	DB  000H,000H,000H,000H,000H,000H,001H,0FFH,000H,000H,000H,000H,000H,000H,000H,000H
	DB  001H,0FFH,03FH,0FFH,0FFH,0FFH,0F8H,00FH,0FFH,0FFH,0FCH,000H,03FH,0FFH,0FFH,0FFH
	DB  0F8H,00FH,0FFH,0FFH,0FEH,000H,03FH,0FFH,0FFH,0FFH,0F0H,087H,0FFH,0FFH,0FFH,0FFH
	DB  0FFH,0E0H,003H,0FFH,0E1H,0C3H,0FFH,0E0H,003H,0FFH,0FFH,0E0H,003H,0FFH,0C3H,0E1H
	DB  0FFH,0E0H,003H,0FFH,0FFH,0E7H,0F3H,0FFH,087H,0F0H,0FFH,0E7H,0F3H,0FFH,0FFH,0E7H
	DB  0F3H,0FFH,00FH,0F8H,07FH,0E7H,0F3H,0FFH,0FFH,0E7H,0F3H,0FEH,01FH,0FCH,03FH,0E7H
	DB  0F3H,0FFH,0FFH,0E7H,0F0H,000H,03FH,0FEH,000H,007H,0F3H,0FFH,0FFH,0E7H,0F0H,000H
	DB  03FH,0FEH,000H,007H,0F3H,0FFH,000H,007H,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0F0H,000H
	DB  000H,007H,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0F0H,000H
data ends

stack segment
	dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
stack ends

code segment
start:
	mov ax, data
	mov ds, ax
	mov bx, 0

	mov ax, stack
	mov ss, ax
	mov sp, 40h

	mov ax, 0b800h
	mov es, ax
	mov bp, 0
	mov si, 0

	;以下代码描绘迷宫
	mov cx, 25
l1:
	push cx
	mov si, 0
	mov cx, 10
l2:
	push cx
	mov al, [bx]
	mov ah, 0
	mov di, 0
	call printByte ;打印ax中的一个字节内容,注意先化成二进制
	inc bx
	pop cx
	loop l2
	add bp, 160 ;换行
	pop cx
	loop l1

	mov bp, 1600 		;描绘终点
	mov si, 158
	mov al, 0
	mov ah, 00100000b
	mov es:[bp + si], ax

	mov bp, 2240 		;描绘起点
	mov si, 158
	mov al, 17
	mov ah, 00000001b
	mov es:[bp + si], ax
	mov dx, 2 			;0、1、2、3分别对应 上、下、左、右

	;以下代码实现走迷宫的左手逃生法则,终点坐标是(1600,158),起点坐标是(2240,158),障碍物内容4000h,终点内容是2000h
go:
	call sleep
	cmp es:[bp + si], 2000h
	je break

	call left 	;该方法计算出当前位置左边的坐标,结果存放在bx,di中,dx保存当前面朝的方向
	call check	;该方法计算出bx、di是否超出范围,若超出ax=0,反之ax=1
	cmp ax, 0
	je goForward
	mov ax, 0 	;ax=0表示要在当前面朝的方向(dx)朝左转
	cmp word ptr es:[bx + di], 0
	je walk 	;该方法将当前位置移动到bx,di坐标

goForward:
	call forward
	call check
	cmp ax, 0
	je goRight
	mov ax, 1 	;ax=1表示要在当前面朝的方向(dx)继续走
	cmp word ptr es:[bx + di], 0
	je walk

goRight:
	call right
	mov ax, 2 	;ax=2表示要在当前面朝的方向(dx)朝右转
	cmp word ptr es:[bx + di], 0
	je walk

	;jmp go
break:
	mov ax, 4c00h
	int 21h

walk:  				;ax=0-朝左走  1-朝前走  2-朝右走(dx代表当前面向哪个方向 0-上  1-下  2-左  3-右)
	cmp dx, 0
	je faceUp3
	cmp dx, 1
	je faceDown3
	cmp dx, 2
	je faceLeft3
	cmp dx, 3
	je faceRight3

faceUp3:
	cmp ax, 0
	je toLeft
	cmp ax, 1
	je toUp
	cmp ax, 2
	je toRight
faceDown3:
	cmp ax, 0
	je toRight
	cmp ax, 1
	je toDown
	cmp ax, 2
	je toLeft
faceLeft3:
	cmp ax, 0
	je toDown
	cmp ax, 1
	je toLeft
	cmp ax, 2
	je toUp
faceRight3:
	cmp ax, 0
	je toUp
	cmp ax, 1
	je toRight
	cmp ax, 2
	je toDown

toUp:
	mov al, 30
	mov dx, 0
	jmp endWalk
toDown:
	mov al, 31
	mov dx, 1
	jmp endWalk
toLeft:
	mov al, 17
	mov dx, 2
	jmp endWalk
toRight:
	mov al, 16
	mov dx, 3
	jmp endWalk

endWalk:
	mov ah, 00000001b
	mov es:[bp + si], ax
	mov bp, bx
	mov si, di
	mov es:[bp + si], ax
	jmp go

left:
	mov bx, bp
	mov di, si

	cmp dx, 0
	je faceUp0
	cmp dx, 1
	je faceDown0
	cmp dx, 2
	je faceLeft0
	cmp dx, 3
	je faceRight0

faceUp0:
	sub di, 2
	jmp continue0
faceDown0:
	add di, 2
	jmp continue0
faceLeft0:
	add bx, 160
	jmp continue0
faceRight0:
	sub bx, 160
continue0:
	ret

forward:
	mov bx, bp
	mov di, si

	cmp dx, 0
	je faceUp1
	cmp dx, 1
	je faceDown1
	cmp dx, 2
	je faceLeft1
	cmp dx, 3
	je faceRight1

faceUp1:
	sub bx, 160
	jmp continue1
faceDown1:
	add bx, 160
	jmp continue1
faceLeft1:
	sub di, 2
	jmp continue1
faceRight1:
	add di, 2
continue1:
	ret

right:
	mov bx, bp
	mov di, si

	cmp dx, 0
	je faceUp2
	cmp dx, 1
	je faceDown2
	cmp dx, 2
	je faceLeft2
	cmp dx, 3
	je faceRight2

faceUp2:
	add di, 2
	jmp continue2
faceDown2:
	sub di, 2
	jmp continue2
faceLeft2:
	sub bx, 160
	jmp continue2
faceRight2:
	add bx, 160
continue2:
	ret

check: 				;检查bx,di是否越出屏幕范围
	cmp bx, 0
	jb outBound
	cmp di, 0
	jb outBound
	cmp bx, 0f00h
	ja outBound
	cmp di, 158
	ja outBound

	mov ax, 1
	jmp next
outBound:
	mov ax, 0
next:
	ret

sleep:
 	mov cx,00ffh  ;注意:改变此cx值可改变延时的时间长短
s0:	push cx
    mov cx,00fffh
s1:	loop s1
    pop cx
    loop s0
    ret

printByte:
	mov cx, 8
l3:
	mov dl, 2
	div dl
	mov dl, al
	mov dh, 0
	mov al, ah
	mov ah, 0
	push ax
	mov ax, dx
	loop l3

	mov cx, 8 	;先解码成8位二进制数字
l4:
	pop ax
	call printBit
	loop l4
	ret

printBit:
	cmp ax, 1
	je ok
	mov dl, 0
	mov dh, 0
	jmp exit
ok:	mov dl, 0
	mov dh, 01000000b
exit:
	mov es:[bp + si], dx
	add si, 2
	ret
code ends
end start


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值