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

📄 241.asm

📁 1. 要求程序建立一个可存放50项的电话号码表
💻 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 ?                 ;排序时的tel_tab尾地址指针
namtemp db 28 dup(?),13,10,'$'         ;临时保存表中一项
swap db 0                           ;排序中是否有交换的标志位

msg_count db 'Please enter the count 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 'Do you want a telephone number?(Y/N)','$'
msg_sname db 'name?',13,10,'$'
msg_outtitle db 'name                tel.',13,10,'$'
msg_nomatch db 'No such name!Do you want to insert this item(Y/N)?',13,10,'$'
msg_result db 'The Phone Dictionary is listed  as follows:',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 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 input_phone
        ;call printline
        ;cmp namcount,1
        ;jb  return1                ;表中项数小于1则要求输入
        call name_sort             ;不小于调用name_sort      
        call printline
       jmp rotate


 exit1: lea dx,msg_illch ;'Error:The number of your enter is not allowed! Please intput the number again!'
       mov ah,9
       int 21h

       jmp again

return: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 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
;mov dh,3d;

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

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

 call printit
 ;a1a2a3... 递推:x=an-1*10+an
 ;mov dl,al;商暂存在bl中
 ;mov dh,ah;余数暂存在dh中
 ;mov bh,0d;
 ;mov ax,bx
 ;mul cl
 ;mov bl,al
 ;add bl,dl

 ;除数ch=ch/10
 mov al,ch
 cbw
 div cl
 mov ch,al
 ;dec dh
 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 + -