汇编电话本
用汇编写出的电话本项目
直接放代码吧
.386
.model flat,stdcall
option casemap:none
include msvcrt.inc
includelib msvcrt.lib
include user32.inc
includelib user32.lib
include windows.inc
include kernel32.inc
includelib kernel32.lib
.data
; 暂停
str_system_pause db “pause”, 0dh, 0ah, 0
; 用于保存菜单的选项
choose dd 0
; 用于存储跳转表的数据
; 跳转表,保存 case 块的地址
jmp_table dd case1, case2, case3, case4,case5,case6
;定义结构体
CONTACTSSTRUCT struct
szName BYTE 25 dup(0) ;name
szPhNmuber BYTE 12 dup(0) ;phone number
CONTACTSSTRUCT ends
PCONTACTSSTRUCT TYPEDEF PTR CONTACTSSTRUCT ;取别名,指针类型
g_stContacts CONTACTSSTRUCT 100 dup(<‘0’>) ;定义结构体数组
g_nCount DWORD 0 ;元素个数
g_nMaxCount DWORD 100 ;MAX元素个数
g_strTemContacts CONTACTSSTRUCT <‘0’,‘0’> ;接收输入信息
;定义格式控制符,用于输入输出时用到的格式控制符
g_szScanfFormat BYTE ‘%s %s’,0h
g_szScanfName BYTE ‘%s’,0h
g_szScanfByte BYTE ‘%c’,0h
.const ;常量数据
sz_put_name db “请输入要添加的用户名,密码:”,0h
sz_find_name db “请输入要查找的用户名:”,0h
sz_change_name db “请输入要修改的name”,0h
sz_remove_name db “请输入要删除的name”,0h
sz_put_number db"please enter a number",0h
g_szOK db"删除OK",0h
; 清空屏幕
str_printf_size db “超出容量”, 0dh, 0ah, 0
; 格式控制符
str_format_int db “%d”, 0
; 菜单项
str_show_menu db “1. 添加数据”, 0dh, 0ah,
“2. 显示数据”, 0dh, 0ah,
“3. 查找数据”, 0dh, 0ah,
“4. 删除数据”, 0dh, 0ah,
“5. 修改数据”, 0dh, 0ah,
“6. 退出程序”, 0dh, 0ah,
"请输入选项: ", 0
; 0dh 0ah == \r\n 0 字符串结尾
;tr_show_menu db “1.添加数据”,
.code
; 清空屏幕
str_system_cls db “cls”, 0
GET_CHAR PROC
push eax
push offset g_szScanfByte;%c
call crt_scanf
add esp,8h
ret
GET_CHAR endp
ADD_USER proc ;无参数
lea eax,sz_put_name
push eax ;提示输入名字
call crt_printf ;打印sz_put_name
add esp,4h ;平衡参数 ;平衡
xor eax,eax
xor ecx,ecx
;cmp ecx,[g_nMaxCount] ;判断是否超过最大容量
lea esi,[g_stContacts]
mov ecx,g_nCount ;获取已存放信息个数
mov eax,sizeof(CONTACTSSTRUCT)
imul eax,ecx
add esi,eax;数组大小,乘以 count
lea edx,[esi+CONTACTSSTRUCT.szName]
lea eax,[esi+CONTACTSSTRUCT.szPhNmuber]
push eax
push edx
;push eax
push offset g_szScanfFormat
call crt_scanf
add esp,12
inc g_nCount ;++
ret
ADD_USER endp
;---------------------------------
FindData proc
xor ecx,ecx
xor eax,eax
xor ebx,ebx
;1.输入数据
lea eax,sz_put_name
push eax ;提示输入名字
call crt_printf ;打印sz_put_name
add esp,4h ;平衡参数 ;平衡
lea edi,[g_strTemContacts.szName]
push edi
push offset g_szScanfName
call crt_scanf
add esp,8
;2.开始查询
mov ecx,0
CYCLE_MARK:
cmp ecx,g_nCount
jz Exit_cycle
;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 ;初始化字符串,因为是25个字节,但末尾是0,而用dword4字节,4*6 24
repe cmpsd dword ptr[esi],dword ptr[edi]
je CARRIEDOUT_MARK
mov ecx,eax
INC ECX ;自增
jmp CYCLE_MARK
CARRIEDOUT_MARK:
;输出信息
mov ecx,eax
lea esi,[g_stContacts]
mov ebx,sizeof(CONTACTSSTRUCT)
imul ebx,ecx
add esi,ebx
lea eax,[esi+CONTACTSSTRUCT.szPhNmuber]
push eax
push offset g_szScanfName
call crt_printf
add esp,8
Exit_cycle:
ret
FindData endp
;修改用户信息
CHANGE PROC
;1.输入信息
push offset sz_change_name
call crt_printf
add esp,4
lea edi,[g_strTemContacts.szName]
push edi
push offset g_szScanfName
call crt_scanf
add esp,8
;2.开始查询
mov ecx,0
CYCLE_MARK:
cmp ecx,g_nCount
jz Exit_cycle ;if 找不到就退出
;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
repe cmpsd dword ptr[esi],dword ptr[edi]
je CARRIEDOUT_MARK
mov ecx,eax
inc ecx
jmp CYCLE_MARK
CARRIEDOUT_MARK:
;修改信息
mov ecx,eax
lea esi,[g_stContacts]
mov ebx,sizeof(CONTACTSSTRUCT)
imul ebx,ecx
add esi,ebx
;1.输入信息
push offset sz_change_name
call crt_printf
add esp,4
;1.1修改信息
lea edx,[esi+CONTACTSSTRUCT.szName]
lea eax,[esi+CONTACTSSTRUCT.szPhNmuber]
push eax
push edx
push offset g_szScanfFormat
call crt_scanf
add esp,12
Exit_cycle:
ret
CHANGE endp
RemoveData proc
;1.输入信息
push offset sz_remove_name
call crt_printf
add esp,4
lea esi,[g_strTemContacts.szName]
push esi
push offset g_szScanfName
call crt_scanf
add esp,8
;2.循环遍历
mov ecx,0
CYCLE_MARK:
cmp ecx,g_nCount
jz Exit_cycle
push ecx ;先push进去
;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 ;初始化字符串,因为是25个字节,但末尾是0,而用dword4字节,4*6 24
repe cmpsd dword ptr[esi],dword ptr[edi]
je CARRIEDOUT_MARK
pop ecx
;mov ecx,eax
INC ECX ;自增
jmp CYCLE_MARK
CARRIEDOUT_MARK:
;删除
;将esi设置为当前要删除的结构体数组
pop ecx
;mov ecx,eax
lea edi,[g_stContacts]
mov ebx,sizeof(CONTACTSSTRUCT)
imul ebx,ecx
add edi,ebx ;edi保存的是,当前要删除的结构体数组的首地址
mov esi,edi
mov ebx,sizeof(CONTACTSSTRUCT)
add esi,ebx ;esi 指向要删除的结构体数组的下一个元素的首地址
add ecx,eax
mov eax,g_nCount
sub eax,ecx
mov ebx,sizeof(CONTACTSSTRUCT)
imul ebx,eax
mov ecx,ebx ;计算need mov的字节
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 2000
call Sleep ;此函数不用自己平衡栈 需要包含头文件include kernel32.inc cludelib kernel32.lib
Exit_cycle:
ret
RemoveData endp
ShowData proc
mov ecx,0
CYCLE_MARK:
cmp ecx,g_nCount
jz CARRIEDOUT_MARK
push ecx;一定要在cmp下,不然在cmp前,一终止,就无法pop了
;造成栈不平衡
;2.依次打印
lea esi,[g_stContacts] ;源串
mov eax,sizeof(CONTACTSSTRUCT)
imul eax,ecx
add esi,eax
;1.1输出
lea edx,[esi+CONTACTSSTRUCT.szName]
lea eax,[esi+CONTACTSSTRUCT.szPhNmuber]
push eax
push edx
push offset g_szScanfFormat
call crt_printf
add esp,12
pop ecx
inc ecx
jmp CYCLE_MARK
CARRIEDOUT_MARK:
ret
ShowData endp
; 函数:退出程序
exit_pragma proc
push 0
call crt_exit
ret
exit_pragma endp
main:
begin_while:
; 打印菜单项: print(arg)
push offset str_show_menu
call crt_printf
; crt 函数是 c 语言提供的的
; 所以需要平衡堆栈 _cdecl
add esp, 4
; 获取用户的输入 scanf("%d", &choose)
push offset choose
push offset str_format_int
call crt_scanf
; 有两个参数,需要平衡 2*4 字节
add esp, 8
; switch case 的实现
; 1. 获取到当前输入的数据对应的[下标]
mov ecx, [choose]
dec ecx
; 2. 判断下标是否在有效范围(case)之内
cmp ecx, 4
; 3. 如果传入的数据不在表中,那么跳转到 default
ja default
; 4. 否则查表进行跳转
jmp dword ptr [jmp_table+ecx*4]
case1:
; 添加数据
call ADD_USER
jmp endswitch
case2:
; 显示数据
call ShowData
jmp endswitch
case3:
; 查找数据
call FindData
jmp endswitch
case4:
;删除数据
call RemoveData
jmp endswitch
case5:
; 修改数据
call CHANGE
jmp endswitch
case6:
; 退出程序
call exit_pragma
jmp endswitch
default:
; 表示输入错误,直接进入下一次循环
jmp begin_while
push 500
call Sleep
endswitch:
; 添加一个暂停
push offset str_system_pause
call crt_system
add esp, 4
; 清空屏幕
push offset str_system_cls
call crt_system
add esp, 4
jmp begin_while
;call ADD_USER
;call FindData
; xor ecx,ecx
; xor eax,eax
; xor ebx,ebx
;
; push offset g_stContacts.szName
; call crt_printf ;打印
; add esp,4h
; push offset g_stContacts.szPhNmuber
; call crt_printf ;打印
; add esp,4h
;
; call ADD_USER
;
; xor ecx,ecx
; xor eax,eax
; xor ebx,ebx
;
; lea esi,[g_stContacts]
; ;mov ecx,g_nCount-1 代表是地址-1 mov ecx,g_nCountv相当于 取了 g_nCount的值放到ecx中
; mov ecx,g_nCount
; dec g_nCount ;获取已存放信息个数
;; sub ecx,1
;;mov ecx,2-1
; mov eax,sizeof(CONTACTSSTRUCT)
; imul eax,ecx
; add esi,eax;数组大小,乘以 count
;
; lea eax,[esi+CONTACTSSTRUCT.szName]
;
; lea edx,[esi+CONTACTSSTRUCT.szPhNmuber]
;
; push edx
;
; push eax
;
; ;push offset g_stContacts.szName
; call crt_printf ;打印
; add esp,4h
; pop edx
; push edx
; ;push offset g_stContacts.szName+25H
; call crt_printf ;打印 打印不出来的原因是因为,上一个call会改变edx中的值
; add esp,4h
ret
end main
end