汇编电话本 15pb

.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
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值