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

📄 phones.asm

📁 汇编语言的实验报告
💻 ASM
字号:
data_seg segment
   namcount dw 0                 
   tel_tab db 50 dup(28 dup(' '))         

   nameitem label byte
   nmax db 21
   ncurlen db ?
   namefld db 21 dup(?)         
   phoneitem label byte
   pmax db 9
   pcurlen db ?
   phonefld db 9 dup(?)         
   addend dw ?                      
   namtemp db 28 dup(?),13,10,'$'         
   swap db 0                           

   msg_count db 'How many records do you want to input?',13,10,'$'
   msg_illcount db 'Error:The number of your enter exceed the limit of 50! Plesae input the number again!',13,10,'$'
   msg_illch db 'Error:The number of your enter is illegal! Please intput the number again!',13,10,'$'
   msg_inputnam db 'Input name:','$'
   msg_inputerr db 'Error:Input error!,please input a name!',13,10,'$'
   msg_inputnum db 'Input a telephone number:','$'
   msg_inquire db 'Want to find a telephone number?(Y/N)','$'
   msg_sname db 'name?',13,10,'$'
   msg_outtitle db 'name                tel.',13,10,'$'
   msg_nomatch db 'No such name!Insert again(Y/N)?',13,10,'$'
   msg_result db 'Phone  list:',13,10,'$'
   bbb   db  '***********************************','$'
   list  db 'names               tel',13,10,'$' 
data_seg ends

stack_seg segment para stack 'stack'      ;定义堆栈段
   dw 256 dup(0)
stack_seg ends

code_seg segment

assume cs:code_seg,ds:data_seg,es:data_seg,ss:stack_seg

main proc far
start:
      mov ax,data_seg
      mov ds,ax                   ;初始化数据段
      mov es,ax                   ;初始化附加段

      cld                         ;df=0
      lea di,tel_tab              ;名字表的首地址放入di

      lea dx,msg_count
      mov ah,9
      int 21h                     ;显示信息0:'How many names do you want to enter?'

again:
      call decibin                ;调用decibin(将输入的十进制次数转换成机器能识别的二进制数)

      cmp dx,2                    ;注意该条语句和下面的跳转语句的位置.计数器(记录名字数的位数)
      call crlf                ;回车换行
      je exit1                   ;一个有效字符都没输入,跳转要求重新输入.输入的为非法字符即非数字则不等输入完就跳出

      push bx
      cmp bx,50 ;
      ja  return                  ;输入的个数大于50出错跳出
                                 ;输入表中项数并保存在bx中

repeat:
       pop bx
       cmp namcount,bx        ;目前项数和要求输入的项数比较,名字数和bx比较
       je  choice                 ;如果所有项都输入完毕则跳到choice排序
       push bx                ;stor_name会用到bx,先保存

       lea dx,msg_inputnam
       mov ah,9
       int 21h               ;要求输入名字
       call input_name            ;调用input_name
       cmp ncurlen,0               ;没有输入了则开始排序,输入名字的字符数为0跳转
       je  choice
       call stor_name
       call input_phone           ;调用input_phone
       jmp  repeat              ;由于tel_tab是顺序连续存储,每一次输入一项后,di即指向下一项的开始,所以无需调整


choice:
       cmp namcount,1
       jb  return1                ;表中项数小于1则要求输入
       call name_sort             ;不小于调用name_sort
        
rotate:
       lea dx,msg_inquire ;输出'Do you want to find a telephone number?(Y/N)'
       mov ah,9
       int 21h                    ;显示是否查找电话号码
       mov ah,1
       int 21h                    ;由键盘输入‘Y’或‘N’

       cmp al,'y'
       je loop0
       cmp al,'Y'
       jne exit                   ;不为‘Y'或'y'跳出转至exit
       jmp loop0                ;  为‘Y'回车、换行

                  

loop0: 
       call crlf
       lea dx,msg_sname                    ;'name?'
       mov ah,9
       int 21h                    ;显示要查询电话的姓名

       call input_name            ;输入姓名
       call name_search           ;调用name_search
       jmp rotate                 ;返回查找另一个电话

insert: 
       call crlf
  
       call stor_name     
                                   ;call printline
       call input_phone             ;cmp namcount,1
                                    ;jb  return1                ;表中项数小于1则要求输入
       call name_sort             ;不小于调用name_sort      
       call printline
       jmp rotate


exit1: 
       lea dx,msg_illch        ;输入错误的数字,要重新输入
       mov ah,9                ;'Error:The number of your enter is not allowed! Please intput the number again!'
       int 21h
       jmp again

return:                      ;超过了50
       lea dx,msg_illcount   ;'Error:The number of your enter exceed the limit of 50! Plesae input the number again!'
       mov ah,9
       int 21h
       jmp again

return1:
       lea dx,msg_inputerr ;输出'Error:Input error!,please input a name!'
       mov ah,9
       int 21h               ;没有输入名字

       jmp repeat            ;出错跳转

exit: 
       call printline      ;输出排序结果

                           ;输入任意字符退出
       mov ah,7
       int 21h
       
       mov ax,4c00h
       int 21h
 main endp                          ;主程序结束


name_search proc near       ;在表中顺序查找输入的名字
       
        lea di,tel_tab                 ;把输入的名字首地址放入di
        push di                          ;保存名字表首址,di为指向tel_tab表项的指针
        mov bx,namcount          ;名字的个数放bx
loop1: 
        lea si,namefld           ;名字的缓存区首地址放入si
        mov cx,20
        repe cmpsb                  ;连续查找匹配名字
        je  found                       ;找到跳转found
        pop di                           ;没找到di出栈
        add di,28                      ;把查找转到下一个名字
        push di
        dec bx
        jnz loop1                       ;循环查找

        lea dx,msg_nomatch
        mov ah,9
        int 21h                          ;一直没找到则显示没有找到名字

        mov ah,1
        int 21h                           ;由键盘输入‘Y’或‘N’
        cmp al,           'y'

        je insert
                           ;cmp al,'Y'                     ;此时di应指向插入位置

        jne loop0                       ;不为‘Y'或'y'跳转至重新输入名字查找
                             ;jmp insert

found: 
        pop di
        lea dx,msg_outtitle
        mov ah,9
        int 21h

        mov si,di                      ;把要找到的内容暂存在namtemp中
        lea di,namtemp
        mov cx,28
        rep movsb

        lea dx,namtemp
        mov ah,9
        int 21h                          ;显示查到的姓名和电话号码
        ret
name_search endp

decibin proc near                ;键盘输入十进制数转换成二进制数
        mov bx,0                            ;bx清零
        mov dx,2                      ;输入数的位数置2

newchar:
        mov ah,1
        int 21h                          ;一号功能调用(输入字符并回显)

        sub al,30h
        jb  exit2                         ;非数字退出
        cmp al,9
        ja  exit2                          ;大于9退出(十进位制数每位0-9)
        cbw                                ;字节转换成字(al->ax)
        xchg ax,bx                     ;交换ax、bx
        mov cx,10
        push dx
        mul cx                           ;先保存,dx×10
        xchg ax,bx                     ;再将ax、bx交换回
        add  bx,ax
        pop  dx
        dec  dx
        jnz  newchar                  ;位数不为0跳转

exit2: ret
decibin endp                          ;结束

input_name proc near          ;子程序(输入名字)
                                                
        lea dx,nameitem
        mov ah,0ah
        int 21h                             ;输入名字并送入缓存区

        call crlf                            ;回车、换行

        mov bh,0
        mov bl,ncurlen               ;把名字的字符个数放入bx低位
        mov cx,21                       ;置循环次数
        sub cx,bx

repeat1:mov namefld[bx],20h
        inc bx
        loop repeat1                    ;输入的名字为20字节,不足的用空格补足
        ret
input_name endp

stor_name proc near              ;子程序(传送名字的每个字母到si)
                                                ;需要事先已设置好di
  inc namcount
        cld                                       ;df=0(从小到大)
        lea si,namefld
        mov cx,20
        rep movsb                       ;重复传送串名字(以字节为单位),直至送满20即cx=0 ,di指向tel_tab
        ret
stor_name endp

input_phone proc near             ;子程序(输入电话号码)
                                                   ;需要事先已设置好di
        lea dx,msg_inputnum
        mov ah,9
        int 21h                                 ;显示要求输入电话号码

        lea dx,phoneitem
        mov ah,10
        int 21h                               ;输入电话号码并送入缓存区
        
        mov bh,0
        mov bl,pcurlen
        mov cx,9                           ;置循环次数
        sub cx,bx

repeat2:mov phonefld[bx],20h
        inc bx
        loop repeat2                      ;输入的电话为8字节,不足的用空格补足

        call crlf

        cld                                       ;df=0
        lea si,phonefld
        mov cx,8
        rep movsb                        ;把输入的号码存入namtab表中,重复传送串电话号码(以字节为单位)
        ret
input_phone endp

name_sort proc near               ;子程序 ;有交换标志的冒泡排序,需要设置di

        push di
        push ax
        push bx
        cmp namcount,1
        jz  exit4                          ;比较名字个数(只有一个名字即退出)

s1:    
        mov swap,0
        sub di,56                             ;di指针后移两个表项,第一次指向倒数第二项,以后每跑一趟前移一项
        mov addend,di                   ;重新计算表尾指针
        lea si,tel_tab

s2:    
        mov cx,20                   ;置循环计数值
        mov di,si
        add di,28                      ;di->后项,si->前项
        mov ax,di                      ;后项保存在ax
        mov bx,si                      ;前项保存在bx
        repe cmpsb                  ;源-目标,即前项如果大于后项,交换;
        jbe s3
        call exchange

s3:    
        mov si,ax
        cmp si,addend
        jbe s2                            ;是否已到namtab表尾,如果没到继续循环
        cmp swap,0                 ;如果有交换,继续下一趟
        jnz s1

exit4: 
        pop bx
        pop ax
        pop di
        ret

name_sort endp

exchange proc near            ;交换tel_tab中di,si所指表项的内容,前项保存在bx
        mov cx,28
        lea di,namtemp
        mov si,bx
        rep movsb
        
        mov cx,28
        mov di,bx
        rep movsb
        
        mov cx,28
        lea si,namtemp
        rep movsb
        
        mov swap,1
        ret
exchange endp

printline proc near                ;输出排序结果,不需要设置di,会改变di值
        push di
        push namcount                   ;printline 会被多次调用,保存namcount的值
  
        call crlf                            ;回车、换行

        lea dx,msg_result          ;'The result of sort is as follows:'
        mov ah,9
        int 21h  
                                           ;显示升序输出姓名、电话
        lea dx,list
        mov ah,9
        int 21h                         
        
        lea dx,bbb
        mov ah,9
        int 21h
        
        call crlf
        call crlf
        
        lea si,tel_tab
loop2:  
        lea di,namtemp
        mov cx,28                       ;si每一次loop2会自动修正
        rep movsb                       ;循环传送姓名、电话至输满27字节即cx=0
        lea dx,namtemp
        mov ah,9
        int 21h                             ;显示姓名、电话
        dec namcount                 ;名字数减1
        jnz loop2                          ;没输完则循环输出

        pop namcount
        pop di
        ret
printline endp

deciasc proc near                   ;把10进制数转换成相应的ASCII码,digit in bl
        mov ch,10d
        mov cl,10d

    re:                                            ;判断退出条件
        cmp ch,0
        je quit

                                                ;取每一10进制位上的数字
        mov al,bl;
        cbw
        div ch;
        mov bl,ah                             ;余数继续除相应权,取相应位的10进制数字

 call printit

       mov al,ch
       cbw
       div cl
       mov ch,al

       jmp re

quit:
     ret
   deciasc endp

printit  proc near
                                              ;输出1位数字对应的ASCII码,binary number in al
      add al,30h
      mov dl,al
      mov ah,2
      int 21h
      ret      ;ret不能少!
printit  endp

crlf proc near 
                                              ;输出回车换行
        mov dl,0dh                          ;mov指令不影响标志位  
        mov ah,2
        int 21h
        mov dl,0ah
        mov ah,2
        int 21h
        ret
crlf endp

code_seg ends
  end start

⌨️ 快捷键说明

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