頭文件
.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 (原因有緩衝)解決方案見代碼