头文件
.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