汇编写的电话本

头文件

.data
;定义结构体
CONTACTSSTRUCT struct
    ;名字
    szName BYTE 25 dup (0)
    ;电话号码
    szPhNumber BYTE 12 dup(0)
CONTACTSSTRUCT ends
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;struct *pstruct
PCONTACTSSTRUCT TYPEDEF PTR CONTACTSSTRUCT
;声明全局变量
;定义结构体数组
g_stContacts CONTACTSSTRUCT 100 dup(<‘0‘>)
g_nCountMax DWORD 100 ;最大存放元素
g_strTemContacts CONTACTSSTRUCT <‘0‘,‘0‘> ;接收输入信息
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
g_szOK BYTE ‘OK‘,0

g_start1 BYTE ‘ 1.添加用户‘,0ah,0dh,0
g_start2 BYTE ‘2.删除用户‘,0ah,0dh,0
g_start3 BYTE ‘3.修改用户‘,0ah,0dh,0
g_start4 BYTE ‘4.查找用户‘,0ah,0dh,0
g_start7 BYTE ‘5.所有用户‘,0ah,0dh,0
g_start5 BYTE ‘请输入选项查:‘,0

g_szstartFormat BYTE ‘%s %s %s %s %s %s‘,0
;错误提示
g_start6 BYTE ‘输入错误请重新输入!!!‘,0
g_szstart6Format BYTE ‘%s‘,0ah,0dh,0
;用于接收
g_num DWORD 0
g_szstart7Format BYTE ‘%d‘,0
;addfunc
g_szAddStr BYTE ‘请输入用户名密码格式如:allen 123‘,0ah,0dh,0
g_szretur BYTE ‘增加成功!!!‘,0ah,0dh,0
;removefunc
g_szremoveAddStr BYTE ‘请输入要删除的用户名如:allen ‘,0ah,0dh,0
g_szremoveretur BYTE ‘删除操作完毕!!!‘,0ah,0dh,0
g_szremovenot BYTE ‘没有,删除失败!!!‘,0ah,0dh,0
;changefunc ModifyData
;定义格式控制符
g_szScanfFormat BYTE ‘%s %s‘,0
g_szchangeAddStr BYTE ‘请输入要修改的用户名如:allen ‘,0ah,0dh,0
g_szchangeAdd BYTE ‘%s‘,0
g_szchangeretur BYTE ‘修改完毕!!!‘,0ah,0dh,0
g_szchangernot BYTE ‘没有,修改失败!!!‘,0ah,0dh,0
g_szchange BYTE ‘请输入用户名密码格式如:allen 123‘,0ah,0dh,0
;checkfunc
g_szcheckAddStr BYTE ‘请输入要查找的用户名如:allen ‘,0ah,0dh,0
g_szcheck BYTE ‘没找到!!!‘,0ah,0dh,0
;接收一个名字
g_szScanName BYTE ‘%s‘,0   ;输入这里不通用这种方式0ah,0dh,0
;输出一个密码
g_szScanPasswd BYTE ‘%s‘,0ah,0dh,0 

;元素个数
g_nCount DWORD 0
g_szCount BYTE ‘当前总个数%d‘,0ah,0dh,0 

;FindDataAll
g_szFindDataAll BYTE ‘%s----%s‘,0ah,0dh,0
g_szcheckretur BYTE ‘查询一条完毕!!!‘,0ah,0dh,0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

main函数

.386
.model flat,stdcall
option casemap:none
include passwd.Inc
include msvcrt.inc ;c函数头文件
includelib msvcrt.lib;c函数库
include kernel32.inc
includelib kernel32.lib
;这里都是用的全局要清理
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    ;push ebx
    ;mov ebx,sizeof(CONTACTSSTRUCT)
    ;push ebx
    ;push 0
    ;push edi
    ;call crt_memset
    ;add esp,12
    ;pop ebx
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
;添加用户信息
ADD_USER proc ;无参数
    pushad ;全部入栈
;----------------------------------------------------------------
    lea eax,g_szAddStr
    push eax
    call crt_printf     ;调用格式 crt_xxx
    add esp,4
    lea esi,[g_stContacts];保存数据的结构体数组
    mov ecx,g_nCount;获取当前已经插入的用户个数
    mov eax,sizeof(CONTACTSSTRUCT) ;计算大小
    imul eax,ecx
    add esi,eax ;移动结构体数组的指针(用户个数*结构体的大小)
    lea eax,[esi+CONTACTSSTRUCT.szPhNumber] ;电话号码
    lea edx,[esi+CONTACTSSTRUCT.szName] ;用户名
    push eax
    push edx
    push offset g_szScanfFormat ;g_szScanfFormat BYTE ‘%s %s‘,0
    call crt_scanf
    add esp,12
    ;元素个数
    ;g_nCount DWORD 0
    inc g_nCount
;----------------------------------------------------------------
        lea eax,g_szretur   ;g_szretur BYTE ‘增加成功!!!‘,0ah,0dh,0
    push eax
    call crt_printf     ;调用格式 crt_xxx
    add esp,4
    popad ;全部出栈
    ret
ADD_USER endp
;查询用户信息
FindData proc
    pushad ;全部入栈
    lea eax,g_szcheckAddStr
    push eax
    call crt_printf     ;调用格式 crt_xxx
    add esp,4
;----------------------------------------------------------------
    ;1.输入数据
    ;定义结构体数组
    ;接收用户名
    lea edi,[g_strTemContacts.szName];保存结构体中名字的地址
    push edi
    ;g_szScanName BYTE ‘%s‘,0
    push offset g_szScanName
    call crt_scanf
    add esp,8
    ;开始查询
    mov ecx,0 ;初始化循环次数(默认从0开始循环)
CYCLE_MARK:   ;标号
    cmp ecx,g_nCount
    ;如果相等就说明没有数据了
    je allennot     ;ret
    mov eax,sizeof(CONTACTSSTRUCT) ;计算大小
    imul eax,ecx               ;相乘
    ;2.1根据ecx的值找到下一个结构体名字数组的地址
    lea esi,[g_stContacts] ;保存数据的结构体数组首地址
    add esi,eax        ;偏移
    lea edi,[g_strTemContacts.szName];刚输入的名字的地址
    ;2.2比较字符串
    mov eax,ecx ;保存外层循环的次数
    mov ecx,6 ;初始化串操作循环次数(4字节比较)   4*6=24  加上最后一个==25
    repe cmpsd dword ptr [esi],dword ptr [edi] ;查看repe系列指令的使用原理
    je CARRIEDOUT_MAKR  ;如果找到则跳转(转出信息)
    mov ecx,eax         ;如果没有  还原ecx
    inc ecx             ;循环次数加1
    jmp CYCLE_MARK      ;无条件跳转到外层循环开始位置
CARRIEDOUT_MAKR:
    ;输出信息
    mov ecx,eax     ;先还原ecx
    lea esi,[g_stContacts]
    mov ebx,sizeof(CONTACTSSTRUCT) ;计算大小
    imul ebx,ecx
    add esi,ebx
    lea eax,[esi+CONTACTSSTRUCT.szPhNumber] ;电话号码
    push eax
    push offset g_szScanPasswd
    call crt_printf
    add esp,8
    ;输出完成退出
    jmp allenretn
;----------------------------------------------------------------
allennot:           ;没有
    lea eax,g_szcheck
    push eax
    call crt_printf     ;调用格式 crt_xxx
    add esp,4
    popad ;全部出栈
    ret
allenretn:          ;找到了
    lea eax,g_szcheckretur
    push eax
    call crt_printf     ;调用格式 crt_xxx
    add esp,4
    popad ;全部出栈
    ret
FindData endp

;查看所有信息
FindDataAll proc
    pushad ;全部入栈
;----------------------------------------------------------------
    ;开始查询
    ;i=0
    mov ecx,0 ;初始化循环次数(默认从0开始循环)
    lea esi,[g_stContacts] ;保存数据的结构体数组
CYCLE_MARK:   ;标号
    cmp ecx,g_nCount
    ;如果相等就说明没有数据了
     je allenretn     ;ret
    mov eax,sizeof(CONTACTSSTRUCT) ;计算大小
    imul eax,ecx
    ;2.1根据ecx的值找到下一个结构体名字数组的地址
    add esi,eax
    push ecx ;保存ecx

    lea edx,[esi+CONTACTSSTRUCT.szName];当前结构体在数组中的首地址
    lea ebx,[esi+CONTACTSSTRUCT.szPhNumber];加上名字偏移就是电话了
    push ebx
    push edx
    push offset g_szFindDataAll  ;g_szFindDataAll BYTE ‘%s----%d‘,0ah,0dh,0
    call crt_printf
    add esp,12

    ;还原ecx
    pop ecx
    inc ecx  ;++i
    jmp CYCLE_MARK
;----------------------------------------------------------------
allenretn:
    lea eax,g_szcheckretur
    push eax
    call crt_printf     ;调用格式 crt_xxx
    add esp,4
    popad ;全部出栈
    ret
FindDataAll endp
;修改用户信息
ModifyData proc
    pushad ;全部入栈
    lea eax,g_szchangeAddStr
    push eax
    call crt_printf     ;调用格式 crt_xxx
    add esp,4
;----------------------------------------------------------------
;因为修改信息的第一步也是先要将当前输入的信息在已保存的数组中查询
;1.输入数据   g_strTemContacts CONTACTSSTRUCT <‘0‘,‘0‘> ;接收输入信息
    lea edi,[g_strTemContacts.szName];保存结构体中名字的地址
    push edi
    ;g_szScanName BYTE ‘%s‘,0
    push offset g_szchangeAdd
    call crt_scanf
    add esp,8
;2.开始查询
    mov ecx,0 ;初始化循环次数(默认从0开始循环)
CYCLE_MARK:   ;标号
    cmp ecx,g_nCount
    ;如果相等就说明查找完毕没找到
     je allennot     ;ret
;2.1根据ecx 的值找到下一个结构体名字数组的地址
    lea esi,[g_stContacts] ;保存数据的结构体数组
    lea edi,[g_strTemContacts.szName];刚输入的名字
    mov eax,sizeof(CONTACTSSTRUCT) ;计算大小
    imul eax,ecx
    add esi,eax
;2.2比较字符串
    mov eax,ecx ;保存循环次数
    mov ecx,6 ;初始化串操作循环次数(4字节比较)
    repe cmpsd dword ptr [esi],dword ptr [edi] ;查看repe系列指令的使用原理
    je CARRIEDOUT_MAKR  ;如果找到则跳转(转出信息)
    mov ecx,eax         ;如果没有  还原ecx
    inc ecx             ;循环次数加1
    jmp CYCLE_MARK      ;无条件跳转到外层循环开始位置
CARRIEDOUT_MAKR:
;----------------------------------------------------------------
    pushad ;全部入栈
    lea eax,g_szchange
    push eax
    call crt_printf     ;g_szchange BYTE ‘请输入用户名密码格式如:allen 123‘,0ah,0dh,0
    add esp,4
    popad ;全部出栈
;----------------------------------------------------------------
    ;修改信息
    mov ecx,eax
    lea esi,[g_stContacts]
    mov ebx,sizeof(CONTACTSSTRUCT) ;计算大小
    imul ebx,ecx
    add esi,ebx
    lea edx,[esi+CONTACTSSTRUCT.szName] ;用户名
    lea eax,[esi+CONTACTSSTRUCT.szPhNumber] ;电话号码
    push eax
    push edx
    push offset g_szScanfFormat ;g_szScanfFormat BYTE ‘%s %s‘,0
    call crt_scanf
    add esp,12    ;add esp,8
    jmp allenretn
;----------------------------------------------------------------
allennot:           ;没有
    lea eax,g_szchangernot
    push eax
    call crt_printf     ;调用格式 crt_xxx
    add esp,4
    popad ;全部出栈
    ret
allenretn:           ;成功
    lea eax,g_szchangeretur
    push eax
    call crt_printf     ;调用格式 crt_xxx
    add esp,4
    popad ;全部出栈
    ret
ModifyData endp
;删除用户信息
RemoveData proc
    pushad ;全部入栈
    lea eax,g_szremoveAddStr
    push eax
    call crt_printf     ;调用格式 crt_xxx
    add esp,4
;----------------------------------------------------------------
;1.输入数据
    lea edi,[g_strTemContacts.szName];保存要删除的用户名
    push edi
    ;g_szScanName BYTE ‘%s‘,0
    push offset g_szScanName
    call crt_scanf
    add esp,8
;2.开始查询
    mov ecx,0 ;初始化循环次数(默认从0开始循环)
CYCLE_MARK:   ;标号
    cmp ecx,g_nCount
    ;如果相等就说明查找完毕
     je allennot     ;ret
;2.1根据ecx 的值找到下一个结构体名字数组的地址
    lea esi,[g_stContacts] ;保存数据的结构体数组
    lea edi,[g_strTemContacts.szName];刚接收的用户名
    mov eax,sizeof(CONTACTSSTRUCT) ;计算大小
    imul eax,ecx
    add esi,eax
;2.2比较字符串
    mov eax,ecx ;保存循环次数
    mov ecx,6 ;初始化串操作循环次数(4字节比较)
    repe cmpsd dword ptr [esi],dword ptr [edi] ;查看repe系列指令的使用原理
    je CARRIEDOUT_MAKR  ;如果找到则跳转(转出信息)
    mov ecx,eax         ;如果没有  还原ecx
    inc ecx             ;循环次数加1
    jmp CYCLE_MARK      ;无条件跳转到外层循环开始位置
CARRIEDOUT_MAKR:
;删除
;将esi设置为当前要删除的结构体数组的首地址
    mov ecx,eax ;eax 是在上面获取到的表示当前找到的数据的位置
    lea edi,[g_stContacts]
    mov ebx,sizeof(CONTACTSSTRUCT) ;计算大小
    imul ebx,ecx
    add edi,ebx ;edi此时保存的是当前要删除的结构体数组的首地址
    mov esi,edi ;esi此时也是当前要删除的结构 体数组的首地址
    mov ebx,sizeof(CONTACTSSTRUCT) ;计算大小
    add esi,ebx ;esi此时也是当前要删除的结构体数组的下一个首地址
    add ecx,1   ;因为保存数据时是从数组0开始的,所以加1用于计算需要
            ;移动多少个元素,和数据结构中的线性表一样,蹭某个元素
            ;被删除了后面的元素向前移动
    mov eax,g_nCount
    sub eax,ecx ;需要移动的次数
    mov ebx,sizeof(CONTACTSSTRUCT) ;计算大小
    imul ebx,ecx
    mov ecx,ebx   ;计算需要移动的字节
    rep movs BYTE ptr[edi],BYTE ptr[esi] ;开始移动(以一个字节的大小的移动)
                         ;移动完成后删除最后一个结构体中的信息
    mov ebx,sizeof(CONTACTSSTRUCT) ;计算大小
    push ebx ;大小
    push 0   ;内容
    push edi ;删除的首地址
    call crt_memset ;调用置初始化函数
    add esp,12
    dec g_nCount
    push offset g_szOK  ;操作成功
    call crt_printf
    add esp,4
    push 20
    call Sleep
    ;add esp,4
    jmp allenretn
;----------------------------------------------------------------
allennot:           ;没有
    lea eax,g_szremovenot
    push eax
    call crt_printf     ;调用格式 crt_xxx
    add esp,4
    popad ;全部出栈
    ret
allenretn:
    lea eax,g_szremoveretur
    push eax
    call crt_printf     ;调用格式 crt_xxx
    add esp,4
    popad ;全部出栈
    ret

RemoveData endp

;main
start:
    ;元素个数
    ;g_nCount DWORD 0
    ;g_szCount BYTE ‘%d‘,0ah,0dh,0
    ;输出当前总个数
    push g_nCount
    push offset g_szCount
    call crt_printf
    add esp,8
    ;g_start5 BYTE ‘请输入选项查:‘,0
        push offset g_start5
        push offset g_start7
    push offset g_start4
    push offset g_start3
    push offset g_start2
    push offset g_start1
    push offset g_szstartFormat
    call crt_printf     ;调用格式 crt_xxx
    add esp,24

allen:
    ;scanf() 接收一个整数保存到g_num
    mov g_num,0;清0
    push offset g_num
    ;push eax   不能这样必须是一个地址
    ;g_szstart7Format BYTE ‘%d‘,0
    push offset g_szstart7Format
    call crt_scanf
    add esp,8
    cmp eax,1   ;与crt_scanf的返回值比较就是接收的本来是数字就返回成功1 如果你打的不是字母就返回0
    jnz @T1
    ;mov g_num,eax
    ;mov eax,g_num
    ;if ==1
    cmp g_num,1
    je  myadd
    ;if==2
    cmp g_num,2
    je myremove
    ;if==3
    cmp g_num,3
    je mychange
    ;if===4
    cmp g_num,4
    je mycheck
    ;if===5
    cmp g_num,5
    je mycheckall
    ;else continue
    push offset g_start6
    push offset g_szstart6Format
    call crt_printf     ;调用格式 crt_xxx
    add esp,8
    jmp start
;增
myadd:
    call ADD_USER
        jmp start
;删
myremove:
    call RemoveData
    jmp start
;改
mychange:
    call ModifyData
    jmp start
;查
mycheck:
    call FindData
        jmp start
;查all
mycheckall:
    call FindDataAll
        jmp start

@T1:
        call crt_getchar ;用这个把字母缓冲掉
        cmp eax,0ah      ;一直比对到最后0ah表示换行或回车
        jnz @T1
        push offset g_start6
    push offset g_szstart6Format
    call crt_printf     ;调用格式 crt_xxx
    add esp,8
        jmp start
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        invoke crt__exit, 0
end start
end

有个 bug 要清缓冲(清缓冲的代码在最上面的注释里)就是你所有接收都用的一个结构体所以导致有缓冲 清缓冲思路是你用完那个结构体在后面把他清为 0
win 32汇编 中有个非常严重的问题是你调用 scanf 接收的是%d如果你输入字符串 会死循环下次不会再调 scanf (原因有缓冲)解决方案见代码

原文地址:http://blog.51cto.com/haidragon/2103265

时间: 2024-08-30 07:45:27

汇编写的电话本的相关文章

记一次开发:Qt简单电话本程序

前言 断断续续学习C++一年了,现在要做课设,觉得控制台界面实在太难看,于是用Qt做一个图形化的程序出来. 学习Qt也没有多久,只是了解了个大概,这次开发基本上是啃了2天的官方帮助文档,然后利用各种Qt提供的轮子实现的.有些地方做的确实还很不完善,不过似乎没有什么致命的bug. 代码质量底下,谨慎模仿. Qt真的是一个很好的C++扩展库,学习完C++觉得没有用武之地的可以去学习一下Qt来开发几个图形化软件来练练手. 项目介绍 实现一个简单的电话本程序,能够实现添加.查找.修改.删除.保存到文件等

用结构体实现一个电话本

结构体是c语言又一个存储数据的类型,那么用结构体怎么实现一个简单的可以存储1000个人信息的电话本呢?     一.首先需要定义一个结构体,包含一个人的信息(比如姓名,性别,年龄,电话,住址等等).我们先来定义一个结构体.     typedef struct Pdhb-info     {       char name[5];       char sex[3];       int age;       char tele[12];       char addr[30];     }Pd

java模拟而一个电话本操作

哈哈,大家平时都在使用电话本,下面使用java来模拟而一个简单的电话本吧... 首先给出联系人的抽象类 package net.itaem.po; /** * * 电话人的信息 * */ public class User { private String name; private String phoneNumber; private String companyName; private String email; private String address; private Strin

jdbc电话本项目

整体思路:在登陆之后才能查看自己的电话本,电话本中包含用户名,联系人名字,电话,性别,分类: 1.登陆注册页面--数据库User表,注册登陆使用 2.电话本的前段显示,用表格和表单, 3.创建存取的电话本的表的类,实现各种setget方法及构造方法 4.电话本需要查询,删除,添加,修改的功能,创建java文件实现这些方法 5.创建各种方法的servlet,实现这些功能, 注意:进行非空验证,还有就是在电话本的存储的表中要有隐藏的id,通过前台传入id,作为主键去判断实现那些方法,在登陆之后要注意

ios开发-电话本的设计与实现

#import <UIKit/UIKit.h> #import "SubViewController.h" @interface ViewController : UIViewController<UITableViewDataSource,UITableViewDelegate,SubViewControllerDelegate> @end #import "SubViewController.h" @interface SubViewCo

WP8 电话本编程

通讯录搜索:http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh286416(v=vs.105).aspx过滤条件:http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh286417(v=vs.105).aspx 程序联系人存储的API在空间Windows.Phone.PersonalInformation下,下面来看一下如何去使用这些API来操作联系

微信电话本 扒不掉运营商的底裤

网络通话想成为4G时代的敲门砖,除非移动互联网覆盖到全国每一个角落,包括罕有人烟的地带,就如基础通信网一样. 文/张书乐 <计算机应用文摘>2014年12月上旬刊 11月11日, 这边厢阿里巴巴的光棍节大战正如火如荼,那边厢腾讯不动神色的推出微信电话本,该APP1.0.0版本当日登录苹果和安卓应用商店.一时间,对电商大战有点审美疲劳的舆论,把注意力扑向了微信电话本,言论大同小异,无外乎张小龙再次出手,在微信OTT了运营商的短信.彩信业务后,微信电话本再次向运营商宣战,这次的进攻方向是对手的根据

AT&amp;T汇编——写在开始之前

不知不觉,大三就快结束了,所学的计算机相关知识也基本可以说是教完了,该毕业了,所以,打算对自己所学的比较深入的和感兴趣的知识进行一场回笼.也当作是大学的回忆吧. 计划写的内容在: 1.汇编语言 2.C/C++语言 3.Linux c编程 4.linux 网络编程 5.STL源码阅读 6.nginx源代码阅读 不知道写完这些东西,是不是该毕业了. 有人说,要深入理解计算机,有两个途径:自底向上和自顶向下.我想,对于自己,更适合从最基本的开始,由底层向高层前进. 所以, 先拿汇编语言下手吧! 说到汇

小米畅聊也将瞄准镜对向微信电话本

早在10月份,小米已经让少量用户秘密测试“小米畅聊”.最近小米刚刚获得了虚拟运营商牌照,小米畅聊推出在即,镜头瞄向微信电话本.小米畅聊原本应该先于微信电话本发布的,可虚拟运营商牌照久久不下来.不过小米或许会凭借这块拍照实现弯道超车,毕竟微信电话本还是类VOIP应用. 目前小米畅聊还处于测试阶段测试期间,用户可实现彼此之间的免费通话.根据描述,小米用户可通过MIUI论坛申请测试体验,测试时间为 2014-10-1至2014-12-31,每个月最多可申请300分钟免费时长:不支持拨打国际电话.服务短