汇编语言的代码在dosboxs上出了点问题,有大神帮忙解决一下吗?

初学汇编,小白一枚,不知道错在哪里了,求大神带飞,代码是在源码中国下载的,在dosbox显示这样,

;***********************************************************************************************************************
;程序功能:
;完成小车的自动和手动沿轨道行驶的过程,并具有计时功能
;***********************************************************************************************************************
;运行说明:
;程序运行之后,即显示出轨道和小车;
;按键‘a’或‘m’选择自动还是手动(a为自动,m为手动),按‘s’键启动小车;
;手动时,按方向键控制小车方向,撞到轨道时,小车会停止并闪动;
;小车到达终点后会自动停车,之后按‘r’键可使小车回到起点,然后重新选择小车的运行得方式;
;小车行驶过程中,计时器计时,到达终点则停止计时;
;手动时,按‘t’暂停,‘c’键继续,此间计时不停止;
;小车回到起点位置后,按下‘s’键计时清零,并重新进行下一次的计时;
;小车处于未选定模式和手动运行时可按Esc键退出运行。
;***********************************************************************************************************************


stack segment 'stack'
      db 256 dup(0)
stack ends

data segment
count    dw 0
sec      dw 0
min      dw 0
save_lc  dw 2 dup(?)

car db 0,7,0,0,0,0,0,0,7,0                        ;车的图案,10行10列
    db 7,0,7,0,0,0,0,7,0,7
    db 0,7,9,9,9,9,9,9,7,0
    db 0,0,9,0,0,0,0,9,0,0
    db 0,0,9,0,0,0,0,9,0,0
    db 0,0,9,0,0,0,0,9,0,0
    db 0,0,9,0,0,0,0,9,0,0
    db 0,7,9,9,9,9,9,9,7,0
    db 7,0,7,0,0,0,0,7,0,7
    db 0,7,0,0,0,0,0,0,7,0
 x  dw 180                                        ;起始位置
 y  dw 83

start_flag_1 db 0                                 ;启动标志1
start_flag_2 db 0                                 ;启动标志2
direc_flag db 0                                   ;方向标志
touch_flag db 0                                   ;触轨标志
arrive_flag db 0                                  ;到达标志
turn_x1 dw 138                                    ;拐弯点
turn_y1 dw 28
turn_x2 dw 203
turn_y2 dw 133
turn_x3 dw 135
es_save dw 0                                      ;用于保存图形缓冲区的首地址
mode db ?                                         ;用于保存显示之前显示器的模式

x1 dw ?                                           ;9型轨道的坐标
y1 dw ?
x2 dw ?
y2 dw ?
x3 dw ?
y3 dw ?
x4 dw ?
x_d dw 15                                         ;轨道的宽度

data ends

code segment                                      ;段设置
assume cs:code,ds:data
start:
      mov ax,data
      mov ds,ax
      mov es,ax  

      mov ax,0a000h                               ;图形缓冲区的首地址
      mov es,ax 
      mov es_save,ax                              ;把图形缓冲区的首地址保存在es_save


      mov ah,0fh
      int 10h                                     ;获取显示器显示图形之前的显示模式
      mov mode,al                                 ;把显示模式保存在mode中

      mov ah,35h
      mov al,1ch
      int 21h                                     ;取中段号为1ch(定时中断)的中段向量(即中断程序的入口地址),并把它放在ES:BX中    
      mov save_lc,bx
      mov save_lc+2,es                            ;保存中断向量  

      push ds                                     ;保存ds
      mov dx,seg clint                            ;定时中断服务程序的段地址
      mov ds,dx
      mov dx,offset clint                         ;定时中断的中断服务程序的偏移地址
      mov al,1ch
      mov ah,25h
      int 21h                                     ;设置中断向量,入口:DS:DX=中断向量,al=中断类型号。
                                                  ;即把定时中断的中断服务程序的入口地址放在4*n(其中n为中断类型号)中         
      pop ds                                      ;ds出栈

      in  al,21h                                  ;允许键盘和定时器中断
      and al,11111100b
      out 21h,al
      sti                                         ;开中断

      mov ax,13h
      int 10h                                     ;设置显示器的模式为13h,320×200,256色

      call guidao_9                               ;画轨道
      call picture                                ;显示小车

input:
      mov ah,0
      int 16h                                     ;等待按键输入
      cmp ax,011bh                                ;Esc键退出
      jz  b4

      cmp ax,326dh                                ;选m,则为手动
      jne b1
      call xiaoche_shou
      jmp b2
b1:   cmp ax,1e61h                                ;选a,则为自动  
      jne input                                   ;都没有选,则重新选择输入
      call xiaoche_move

b2:   mov ah,0                                    ;等待按下r键
      int 16h
      cmp ax,1372h                                ;r键的扫描码
      jnz b2                                      ;不是r键,则等待至按下r
      mov start_flag_1,0                          ;是r键,则将起始标志位清零
      mov start_flag_2,0
      mov arrive_flag,0

b3:   call clearpicture                           ;擦除终点的小车
      mov x,180                                   ;小车回到起始位置
      mov y,83        
      call picture                                ;显示小车
      jmp input

b4:   push ds       
      mov dx,save_lc
      mov ax,save_lc+2
      mov ds,ax
      mov al,1ch
      mov ah,25h
      int 21h                                     ;重置之前的中断向量,调用lch
      pop ds

      mov ah,0
      mov al,mode
      int 10h                                     ;把显示器的模式设置为显示图形之前的模式
      mov ax,4c00h                                ;返回dos
      int 21h


;***********************************************************************************************************************
;显示9字型轨道
;***********************************************************************************************************************
guidao_9 proc  
      mov x1,190
      mov y1,95
      mov x2,135
      mov y2,25
      mov x3,215
      mov y3,145
      mov x4,135

      call draw_9_line                            ;外轨道
      mov x1,190
      mov y1,80                                   ;轨道的入口
      mov x2,150
      mov y2,40
      mov x3,200
      mov y3,130
      mov x4,135                                  ;轨道的出口

      call draw_9_line                            ;内轨道
      ret
guidao_9 endp

;******************************画9字**********************************
draw_9_line proc 
      mov cx,x1
      mov dx,y1
      mov di,y2
      mov si,x2

      call hline
      call sline

      mov di,y3
      mov si,x3

      call hline
      call sline

      mov si,x4
      call hline

draw_9_line endp

;*********************画竖线**********************
sline proc                 
      mov al,03h                                  ;设置直线的颜色为青
      mov bh,0                                    ;0页
      mov ah,0ch 
      cmp dx,di
      jg a1line

aline: 
      int 10h                                     ;写图形象素,AL=01h象素值,BH=0页码,(CX、DX)=(0,0)图形坐标列(X)、行(Y)         
      inc dx 
      cmp dx,di                                   ;判断是否到di行      
      jng aline                                   ;没到,则画线
      dec dx                                      ;使下一个点与这一个点重合    
      jmp e3
a1line: 
      int 10h
      dec dx
      cmp dx,di
      jnl a1line
      inc dx
e3:   ret                                         ;到了,则退出       
sline endp

;*********************画横线**********************
hline proc
      mov al,03h                                  ;设置直线的颜色为青
      mov bh,0                                    ;0页
      mov ah,0ch 
      cmp cx,si
      jg b1line       
bline:
      int 10h                                     ;写图形象素,AL=01h象素值,BH=0页码,(CX、DX)=(0,0)图形坐标列(X)、行(Y) 
      inc cx                                      ;画第一点,并让横坐标加一
      cmp cx,si                                   ;判断是否到si列
      jng bline                                   ;没到,则画线
      dec cx                                      ;使下一条线的起点与这一个点重合
      jmp e2
b1line:  
      int 10h                                     ;写图形象素,AL=01h象素值,BH=0页码,(CX、DX)=(0,0)图形坐标列(X)、行(Y) 
      dec cx     
      cmp cx,si
      jnl b1line                                  ;没到,则画线
      inc cx                                      ;使下一条线的起点与这一个点重合     
e2:   ret                                         ;到了,则退出
hline endp


;***********************************************************************************************************************
;显示小车(通过向图形显示缓冲区写点)
;***********************************************************************************************************************
picture proc near
      mov ax,es_save
      mov es,ax

      mov dx,y
      mov bx,0
again: 
      cmp dx,0
      je over
      add bx,320
      dec dx
      jmp again                                   ;找到小车第一个点所在行 

over: mov dx,10                                   
      lea si,car
next1: 
      mov cx,10
      mov di,x                                    ;找到小车第一个点
next: mov al,[si]
      mov es:[bx+di],al                           ;往空位填写数据
      inc si                                      ;指向下一个待填入的数据
      inc di                                      ;指向下一个等待填写的空位
      loop next

      add bx,320                                  ;转到下一行
      dec dx
      jne next1
      ret
picture endp


;***********************************************************************************************************************  
;计时器(中断号为1ch的中断为计时器中断,每55ms中断一次,每秒发生18.2次中断)
;***********************************************************************************************************************       
clint proc far
      push ax                                     ;保护寄存器
      push bx
      push cx
      push dx
      push si
      push di
      push bp
      push sp
      push ds
      push es

      mov bx,data
      mov ds,bx                                   ;设置数据段
      assume ds:data

      cmp arrive_flag,1                           ;判断小车是否到达终点
      jne e6                                      ;没到,则跳至e7
      call disptime                               ;到达,则显示时间
      jmp return                                  ;返回      

e6:   lea bx,count
      inc word ptr[bx]                            ;每产生一次定时中断,count加1
      cmp word ptr[bx],18                         ;判断是否到1秒
      jne e7                                      ;没到,则跳至e6
      call inct                                   ;调整时间     

e7:   mov al,start_flag_1
      and al,start_flag_2
      jnz e8  
      mov al,start_flag_1  
      or al,start_flag_2
      jz return
      jmp e9

e8:   mov count,0
      mov sec,0
      mov min,0
      mov start_flag_2,0          

e9:   call disptime                               ;显示小车

return: 
      pop es
      pop ds
      pop sp
      pop bp
      pop di
      pop si
      pop dx
      pop cx
      pop bx
      pop ax         
      iret
clint endp

;******************判断是否进位*******************
inct proc near
      mov word ptr[bx],0
      add bx,2
      inc word ptr[bx]
      cmp word ptr[bx],60
      jne exit
      call inct
exit: ret
inct endp

;*****************************显示时间********************************
disptime proc near      
      mov ax,min
      call bindec

      mov dl,':'
      mov ah,02h
      int 21h
      mov ax,sec
      call bindec

      mov dl,':'
      mov ah,02h
      int 21h

      mov bx,count
      mov al,55d
      mul bl
      call bindec

      mov dl,0dh                                  ;输出回车,让光标回到起点
      mov ah,02h
      int 21h
      ret
disptime endp

;************把一个三位十进制数显示出来***********
bindec proc near
      mov cx,100d
      call decdiv
      mov cx,10d
      call decdiv
      mov cx,1
      call decdiv
      ret
bindec endp

;********************显示高位*********************
decdiv proc near
      mov dx,0
      div cx
      push dx

      mov dl,al
      add dl,30h
      mov ah,02h
      int 21h                                     ;显示一位

      pop ax
      ret
decdiv endp


;************************************************************************************************************************
;擦除
;************************************************************************************************************************
clearpicture proc near
      mov dx,y
      mov bx,0
again2: 
      cmp dx,0
      je over2
      add bx,320
      dec dx
      jmp again2 
over2: 
      mov dx,10
next12: 
      mov cx,10
      mov di,x
next2: 
      mov al,0                                    ;把该点置为0,即用黑色擦除该点
      mov es:[bx+di],al
      inc di
      loop next2
      add bx,320
      dec dx
      jne next12
      ret
clearpicture endp


;***********************************************************************************************************************
;延时程序
;***********************************************************************************************************************
delay proc near
      push bx
      push cx
      mov bx,1234
back:
      mov cx,66
      push ax
wait1:
      in al,61h
      and al,10h
      cmp al,ah
      je wait1 
      mov ah,al
      loop wait1
      pop ax
      dec bx
      jne back
      pop cx
      pop bx
      ret
delay endp


;***********************************************************************************************************************
;小车自动运行
;***********************************************************************************************************************
xiaoche_move proc
      call picture                                ;转移至picture程序段
ag:   mov ah,7                                    ;中断
      int 21h

      cmp al,'s'                                  ;设置开始键s
      jne ag                                      ;判断是否为s,不是则转至ag中断
      mov start_flag_1,1
      mov start_flag_2,1

start1:
      call clearpicture
      dec x
      call picture
      call delay
      mov si,x
      cmp si,turn_x1                              ;遇到第一个拐弯
      jg start1

start2:
      call clearpicture
      dec y
      call picture
      call delay
      mov si,y
      cmp si,turn_y1                              ;遇到第二个拐弯
      jg start2

start3:
      call clearpicture
      inc x
      call picture
      call delay
      mov si,x
      cmp si,turn_x2                              ;遇到第三个拐弯
      jl start3

start4:
      call clearpicture
      inc y
      call picture
      call delay
      mov si,y
      cmp si,turn_y2                              ;遇到第四个拐弯
      jl start4

start5:
      call clearpicture
      dec x
      call picture
      call delay
      mov si,x
      cmp si,turn_x3                              ;遇到第五个拐弯,即终点
      jg start5
      mov arrive_flag,1
      ret

xiaoche_move endp


;***********************************************************************************************************************
;小车手动运行
;***********************************************************************************************************************
xiaoche_shou proc

j0:   call clearpicture                           ;擦除小车
      call saomiao                                ;键盘扫描

      cmp start_flag_1,1                          ;判断小车是否启动
      jne a8                                      ;没有,则呆在原地不动

      ;判断小车运动的方向
      cmp direc_flag,1        ;上
      jne a1
      dec y
a1:   cmp direc_flag,2        ;下
      jne a2
      inc y
a2:   cmp direc_flag,3        ;左
      jne a3
      dec x   
a3:   cmp direc_flag,4        ;右
      jne a4
      inc x
a4:   call ya_line_do                             ;检测是否碰到轨道
      cmp touch_flag,1
      jne a8                                      ;没有碰到轨道,则继续前进  
      call guidao_9                               ;碰到则重新显示轨道
      mov touch_flag,0                            ;将触轨标志清零
      call back_step                              ;小车后退一步,回到轨道
a8:   call picture
      call delay  
      cmp arrive_flag,1                           ;判断小车是否到达终点,到了则退出
      jne j0  
a9:   ret

xiaoche_shou endp


;***********************************************************************************************************************
;键盘扫描程序
;***********************************************************************************************************************
saomiao proc near  
      mov ah,01h                                  ;从键盘读一个字符,读到的结果为键的扫描码,存放在AH中  
      int 16h   
      jz f                                        ;如果无键按下,则退出
      mov ah,00h                                  ;若有键按下则中断当前  
      int 16h   


      cmp ax,1f73h                                ;s的扫描码
      jne h
      mov start_flag_1,1
      mov start_flag_2,1
      mov direc_flag,0
      mov arrive_flag,0

h:    cmp ax,1474h                                ;t的扫描码
      jne j      
      mov start_flag_1,0  
      mov start_flag_2,1    
k:    call picture    
      mov ah,0
      int 16h
      cmp ax, 2e63h                               ;c的扫描码
      jne k
      mov start_flag_1,1
      mov start_flag_2,0  
      call clearpicture      

j:    cmp ax,4800h                                ;上键的扫描码
      jne a
      mov direc_flag,1

a:    cmp ax,5000h                                ;下键的扫描码       
      jne b  
      mov direc_flag,2

b:    cmp ax,4b00h                                ;左键的扫描码  
      jne g
      mov direc_flag,3

g:    cmp ax,4d00h                                ;右键的扫描码  
      jne f
      mov direc_flag,4
      jmp f

e1:   mov al,mode                                 ;一旦有按键输入,则把显示器的模式设置为画直线之前的模式
      mov ah,0
      int 10h
      mov ax,4c00h              
      int 21h

f:    ret
saomiao endp 


;***********************************************************************************************************************
;小车触轨判断及处理
;***********************************************************************************************************************
ya_line_do proc 
      mov ax,y2
      mov bx,y1
      mov cx,x2
      call ya_y_line

      sub ax,x_d
      add bx,x_d
      sub cx,x_d
      call ya_y_line

      mov ax,y2
      mov bx,y3
      mov cx,x3
      call ya_y_line

      sub ax,x_d
      add bx,x_d
      add cx,x_d
      call ya_y_line

      mov ax,x2
      mov bx,x1
      mov cx,y1
      call ya_x_line

      sub ax,x_d
      add cx,x_d
      call ya_x_line

      mov ax,x2
      mov bx,x3
      mov cx,y2
      call ya_x_line

      sub ax,x_d
      add bx,x_d
      sub cx,x_d
      call ya_x_line

      mov ax,x4
      mov bx,x3
      mov cx,y3
      call ya_x_line

      add bx,x_d
      add cx,x_d
      call ya_x_line

      cmp touch_flag,1
      je e4
      mov ax,y3                                   ;判断是否到终点
      mov bx,ax
      add bx,x_d
      mov cx,x4
      call ya_y_line

      mov al,touch_flag
      mov arrive_flag,al
e4:   ret
ya_line_do endp

;*****************判断是否触到y线*****************
ya_y_line proc                                    ;ax为y1(起点),bx为y2(终点),cx为x1
      cmp x,cx
      je n3 
      mov dx,cx                                   ;注意cx不能变化
      sub dx,9
      cmp x,dx
      jnz n1
n3:   mov dx,ax
      sub dx,9
      cmp y,dx
      jl n1
      cmp y,bx
      jg n1
      mov touch_flag,1 
n1:   ret
ya_y_line endp

;*****************判断是否触到x线*****************
ya_x_line proc                                    ;ax为x1(起点),bx为x2(终点),cx为y1
      cmp y,cx
      je n5
      mov dx,cx                                   ;注意cx不能变化
      sub dx,9
      cmp y,dx
      jnz n2
n5:   mov dx,ax
      sub dx,9
      cmp x,dx
      jl n2
      cmp x,bx
      jg n2
      mov touch_flag,1 
n2:   ret
ya_x_line endp

;************************小车触轨则后退一步***************************
back_step proc
      cmp direc_flag,1                            ;如果碰到轨道,则后退一步
      jne a5
      inc y
a5:   cmp direc_flag,2
      jne a6
      dec y
a6:   cmp direc_flag,3
      jne a7
      inc x   
a7:   cmp direc_flag,4
      jne a8
      dec x
      ret 
back_step endp

;***********************************************************************************************************************
;***********************************************************************************************************************
code ends
end start
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐