程序设计项目一
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