注册 登录
编程论坛 汇编论坛

求大神帮忙看看

C_printf 发布于 2012-07-12 17:00, 1187 次点击
; ?功能:递归搜索C:\\下面的所有文件夹 并且打印出来
;    本人初学汇编,写了如下程序,为方便大家读,刚加了点注释。
;   症状:运行无反应。。。求点破
      .486                      ; create 32 bit code
      .model flat, stdcall      ; 32 bit memory model
      option casemap :none      ; case sensitive

      include \masm32\include\kernel32.inc
      include \masm32\include\windows.inc
      includelib \masm32\lib\kernel32.lib
      serch PROTO :DWORD                    ;申明过程
    .stack
    .data
    despath db 'c:\\',0                        ; 要搜索的路径
    findtype db '*.*',0                        
    uppath  db  '..',0
    szCurDir db 1024 dup(0)                     
    endstr db '$'
    szFullNmae db 1024 dup(0)
    .code
start:
     invoke serch,addr despath                  ;启动过程
    jmp exitme

serch proc szPath:DWORD                           ;过程定义
    local fdata:WIN32_FIND_DATAA
    local hFind:HANDLE

    invoke SetCurrentDirectoryA,addr szPath             ;设置当前工作目录
    or eax,eax
    jz return
    invoke FindFirstFileA,addr findtype,addr fdata          ;查找文件开始
    mov hFind,eax
findloop:
    invoke FindNextFileA,hFind,addr fdata                   ;循环搜索当前目录的文件
    or eax,eax
    jz return
    mov al, fdata.cFileName
    cmp al,'.'
    jz findloop                                             ; 如果 是'.'或者是'..'就continue  我只判断第一个字符
    mov eax,FILE_ATTRIBUTE_DIRECTORY
    and eax,fdata.dwFileAttributes                          ;是否是文件夹
    jz notdirc                                               ;不是文件夹
    invoke GetCurrentDirectoryA,1023,addr szCurDir          ;获取当前目录
    mov edx,ebx                                             ;打印
    mov al,9
    int 21
    invoke serch,fdata.cFileName
    invoke SetCurrentDirectoryA,addr uppath
notdirc:
    nop
return:
    mov eax,0
    ret
   
serch endP
exitme:nop
end start
20 回复
#2
zklhp2012-07-12 17:43
我怎么说呢 没法说了
#3
zklhp2012-07-12 17:45
mov edx,ebx                                             ;打印
    mov al,9
    int 21

这是dos中断 是dos这个16位操作系统的系统调用方法 而你这个程序用的是windows的API

现在都是32位或64位的操作系统了 运行16位程序得用虚拟机 当然微软自带了一个虚拟的环境 这也是为啥16位程序能运行的原因 也就是说 一个32位程序 也就是你这个程序啦 一般是没法调用16位的中断的

而且你这个dos中断调用也写错了。。


[ 本帖最后由 zklhp 于 2012-7-12 17:46 编辑 ]
#4
C_printf2012-07-12 17:48
回复 3楼 zklhp
非常感谢,但是我下了你发的那个plus环境  把09中断改为调用 stdout 还是不行啊
#5
zklhp2012-07-12 17:48
说句不好听的 你这个程序是一四不像

也不是16位的dos汇编 也不是正常的32位汇编
#6
zklhp2012-07-12 17:49
以下是引用C_printf在2012-7-12 17:48:19的发言:

非常感谢,但是我下了你发的那个plus环境  把09中断改为调用 stdout 还是不行啊

你怎么写的呢 发代码才能知道问题在哪
#7
C_printf2012-07-12 17:52
回复 6楼 zklhp
.386
.model flat, stdcall
option casemap :none

include windows.inc
include user32.inc
include kernel32.inc
include masm32.inc
include gdi32.inc

includelib gdi32.lib
includelib user32.lib
includelib kernel32.lib
includelib masm32.lib
include macro.asm
 serch PROTO :DWORD                    ;申明过程
    .stack
    .data
    despath db 'c:\\',0                        ; 要搜索的路径
    findtype db '*.*',0                        
    uppath  db  '..',0
    szCurDir db 1024 dup(0)                     
    endstr db '$'
    szFullNmae db 1024 dup(0)
    .data
    lpMsg        db "Hello World!",0
   
.data?
    buffer    db MAX_PATH dup(?)
   
.CODE
START:
     invoke serch,addr despath                  ;启动过程
    jmp exitme

serch proc szPath:DWORD                           ;过程定义
    local fdata:WIN32_FIND_DATA
    local hFind:HANDLE

    invoke SetCurrentDirectory,addr szPath             ;设置当前工作目录
    or eax,eax
    jz return
    invoke FindFirstFile,addr findtype,addr fdata          ;查找文件开始
    mov hFind,eax
findloop:
    invoke FindNextFile,hFind,addr fdata                   ;循环搜索当前目录的文件
    or eax,eax
    jz return
    mov al, fdata.cFileName
    cmp al,'.'
    jz findloop                                             ; 如果 是'.'或者是'..'就continue  我只判断第一个字符
    mov eax,FILE_ATTRIBUTE_DIRECTORY
    and eax,fdata.dwFileAttributes                          ;是否是文件夹
    jz notdirc                                               ;不是文件夹
    invoke GetCurrentDirectory,1023,addr szCurDir          ;获取当前目录
     invoke locate,2,2
     invoke StdOut,offset szCurDir
    invoke serch,fdata.cFileName
    invoke SetCurrentDirectory,addr uppath
notdirc:
    nop
return:
    mov eax,0
    ret
   
serch endP
exitme:   
    ;暂停显示,回车键关闭
    invoke StdIn,addr buffer,sizeof buffer
    invoke ExitProcess,0
   
end START
#8
zklhp2012-07-12 18:17
程序代码:

.386
.model flat, stdcall
option casemap :none

include windows.inc
include user32.inc
include kernel32.inc
include masm32.inc
include gdi32.inc

includelib gdi32.lib
includelib user32.lib
includelib kernel32.lib
includelib masm32.lib
include macro.asm
serch PROTO :DWORD                    ;申明过程
    ;.stack        ;不用这个
    .data
    despath db 'c:\\',0                        ; 要搜索的路径
    findtype db '*.*',0                       
    uppath  db  '..',0
    szCurDir db 1024 dup(0)                    
    endstr db '$'
    szFullNmae db 1024 dup(0)
    .data
    lpMsg        db "Hello World!",0
  
.data?
    buffer    db MAX_PATH dup(?)
  
.CODE
START:
     invoke serch,addr despath                  ;启动过程
    jmp exitme

serch proc szPath:DWORD                           ;过程定义
    local fdata:WIN32_FIND_DATA
    local hFind:HANDLE
   
    ;这里
    invoke SetCurrentDirectory,szPath             ;设置当前工作目录
    or eax,eax
    jz return
    invoke FindFirstFile,addr findtype,addr fdata          ;查找文件开始
    mov hFind,eax
findloop:
    invoke FindNextFile,hFind,addr fdata                   ;循环搜索当前目录的文件
    or eax,eax
    jz return
    mov al, fdata.cFileName
    cmp al,'.'
    jz findloop                                             ; 如果 是'.'或者是'..'就continue  我只判断第一个字符
    mov eax,FILE_ATTRIBUTE_DIRECTORY
    and eax,fdata.dwFileAttributes                          ;是否是文件夹
    jz findloop                                               ;不是文件夹
    ;invoke GetCurrentDirectory,1023,addr szCurDir          ;获取当前目录
     ;invoke locate,2,2
     lea eax,fdata.cFileName
     invoke StdOut,eax
     invoke StdOut,CTXT(0dh,0ah)
     jmp findloop
    ;invoke serch,fdata.cFileName
    ;invoke SetCurrentDirectory,addr uppath
    invoke CloseHandle,hFind
notdirc:
    nop    ;没有意义
return:
    mov eax,0
    ret
  
serch endP
exitme:  
    ;暂停显示,回车键关闭
    invoke StdOut,CTXT('这种地方要加上提示 比如按回车键退出神马的',0dh,0ah)
    invoke StdIn,addr buffer,sizeof buffer
    invoke ExitProcess,0
  
end START

#9
zklhp2012-07-12 18:19
;这里
    invoke SetCurrentDirectory,szPath             ;设置当前工作目录

比较大的问题是这里 你想想要是加了addr得到的是什么

我给你改成非递归查C盘下的一级目录了。。 主要我不知道你这个写法能不能实现递归查找所有目录
#10
zklhp2012-07-12 18:23
有问题你再问 记得结题哦
#11
C_printf2012-07-13 11:58
回复 10楼 zklhp
程序代码:
;MASMPlus 代码模板 - 控制台程序

.386
.model flat, stdcall
option casemap :none

include windows.inc
include user32.inc
include kernel32.inc
include masm32.inc
include gdi32.inc

includelib gdi32.lib
includelib user32.lib
includelib kernel32.lib
includelib masm32.lib
include macro.asm

 serch PROTO :DWORD                    ;申明过程
    ;.stack
    .data
    despath db 'D:\\',0                        ; 要搜索的路径
    findtype db '*.*',0                       
    uppath  db  '..',0
    szCurDir db 1024 dup(0)                    
    endstr db '$'
    szFullNmae db 1024 dup(0)
    lpMsg        db "Hello World!",0
.data?
    buffer    db MAX_PATH dup(?)
   
.CODE
START:

     invoke serch,addr despath                  ;启动过程

    jmp exitme

serch proc     szPath    :DWORD  ;过程定义
      
      
        local fdata        :WIN32_FIND_DATA
        local hFind        :HANDLE

    invoke SetCurrentDirectory,szPath ;设置当前工作目录
    or eax,eax
    jz return
    invoke FindFirstFile,addr findtype,addr fdata          ;查找文件开始
    mov hFind,eax
findloop:
    invoke FindNextFile,hFind,addr fdata       ;循环搜索当前目录的文件
    or eax,eax
    jz return
    mov al, fdata.cFileName
    cmp al,'.'
    jz findloop                                             ; 如果 是'.'或者是'..'就continue  我只判断第一个字符
    mov eax,FILE_ATTRIBUTE_DIRECTORY
    and eax,fdata.dwFileAttributes                          ;是否是文件夹
    jz notdirc                                               ;不是文件夹
    invoke GetCurrentDirectory,1023,addr szCurDir
    invoke StdOut,offset szCurDir
     lea eax,fdata.cFileName
    invoke StdOut,eax
    invoke StdOut,CTXT(0dh,0ah)
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;   递归核心部分
    mov edx,offset buffer
    invoke StdOut,offset buffer
    lea eax,fdata.cFileName
    mov ebx,0
  loopstrcpy:
    mov al,[eax+ebx]
    mov [edx+ebx],al
    inc ebx
    or al,al
    jnz loopstrcpy
    invoke StdOut,buffer
    invoke serch,buffer
    invoke SetCurrentDirectory,uppath

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    jmp findloop
notdirc:
    nop
    jmp findloop
return:
     invoke CloseHandle,hFind
    mov eax,0
    ret
   
serch endP
exitme:   
    ;暂停显示,回车键关闭
    invoke StdOut,CTXT(0dh,0ah,'这种地方要加上提示 比如按回车键退出神马的',0dh,0ah)
    invoke StdIn,addr buffer,sizeof buffer
    invoke ExitProcess,0
   
end START
现在的问题有更新了,如果注释掉递归核心部分(用分号隔开的) 可以完成一级目录的搜索,但是我想要整个盘符的搜索
但是不注释的话,loopstrcpy这个循环里面的     mov al,[eax+ebx]
                                            mov [edx+ebx],al   
这两句运行弹出错误 难道是buffer的地址在递归的时候变了?
#12
一花一世界2012-07-13 12:16
真心求学
#13
zklhp2012-07-13 12:29
程序代码:

.386
.model flat, stdcall
option casemap :none

include windows.inc
include user32.inc
include kernel32.inc
include masm32.inc
include gdi32.inc

includelib gdi32.lib
includelib user32.lib
includelib kernel32.lib
includelib masm32.lib
include macro.asm
serch PROTO :DWORD                    ;申明过程
    ;.stack
    .data
    despath db 'D:\\',0                        ; 要搜索的路径
    findtype db '*.*',0                     
    uppath  db  '..',0
    szCurDir db 1024 dup(0)                  
    endstr db '$'
    szFullNmae db 1024 dup(0)
    lpMsg        db "Hello World!",0
.data?
    buffer    db MAX_PATH dup(?)
  
.CODE
START:

     invoke serch,addr despath                  ;启动过程

    jmp exitme

serch proc     szPath    :DWORD  ;过程定义
     
     
        local fdata        :WIN32_FIND_DATA
        local hFind        :HANDLE

    invoke SetCurrentDirectory,szPath ;设置当前工作目录
    or eax,eax
    jz return
    invoke FindFirstFile,addr findtype,addr fdata          ;查找文件开始
    mov hFind,eax
findloop:
    invoke FindNextFile,hFind,addr fdata       ;循环搜索当前目录的文件
    or eax,eax
    jz return
    mov al, fdata.cFileName
    cmp al,'.'
    jz findloop                                             ; 如果 是'.'或者是'..'就continue  我只判断第一个字符
    mov eax,FILE_ATTRIBUTE_DIRECTORY
    and eax,fdata.dwFileAttributes                          ;是否是文件夹
    jz notdirc                                               ;不是文件夹
    invoke GetCurrentDirectory,1023,addr szCurDir
    invoke StdOut,offset szCurDir
     lea eax,fdata.cFileName
    invoke StdOut,eax
    invoke StdOut,CTXT(0dh,0ah)
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;   递归核心部分
    invoke StdOut,offset buffer
    ;尽量在调用后改寄存器的值
    mov edx,offset buffer
    lea eax,fdata.cFileName
    mov ebx,0
  loopstrcpy:
    mov al,[eax+ebx]
    mov [edx+ebx],al
    inc ebx
    or al,al
    jnz loopstrcpy
    invoke StdOut,offset buffer
    invoke serch,offset buffer
    invoke SetCurrentDirectory,offset uppath
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    jmp findloop
notdirc:
    nop
    jmp findloop
return:
     invoke CloseHandle,hFind
    mov eax,0
    ret
  
serch endP
exitme:  
    ;暂停显示,回车键关闭
    invoke StdOut,CTXT(0dh,0ah,'这种地方要加上提示 比如按回车键退出神马的',0dh,0ah)
    invoke StdIn,addr buffer,sizeof buffer
    invoke ExitProcess,0
  
end START


错误我能改出来 但我还是怀疑你这个递归方法是否可行
#14
zklhp2012-07-13 12:53
程序代码:

.386
.model flat, stdcall
option casemap :none

include windows.inc
include user32.inc
include kernel32.inc
include masm32.inc
include gdi32.inc

includelib gdi32.lib
includelib user32.lib
includelib kernel32.lib
includelib masm32.lib
include macro.asm
serch PROTO :DWORD                    ;申明过程
    ;.stack
    .data
    despath db 'D:\\',0                        ; 要搜索的路径
    findtype db '*.*',0                     
    uppath  db  '..',0
    szCurDir db 1024 dup(0)                  
    endstr db '$'
    szFullNmae db 1024 dup(0)
    lpMsg        db "Hello World!",0
    szCrLf        db 0dh,0ah,0
.data?
    buffer    db MAX_PATH dup(?)
  
.CODE
START:

     invoke serch,addr despath                  ;启动过程

    jmp exitme

serch proc     szPath    :DWORD  ;过程定义
     
     
        local fdata        :WIN32_FIND_DATA
        local hFind        :HANDLE

    invoke SetCurrentDirectory,szPath ;设置当前工作目录
    or eax,eax
    jz return
    invoke FindFirstFile,addr findtype,addr fdata          ;查找文件开始
    mov hFind,eax
findloop:
    invoke FindNextFile,hFind,addr fdata       ;循环搜索当前目录的文件
    or eax,eax
    jz return
    mov al, fdata.cFileName
    cmp al,'.'
    jz findloop                                             ; 如果 是'.'或者是'..'就continue  我只判断第一个字符
    mov eax,FILE_ATTRIBUTE_DIRECTORY
    and eax,fdata.dwFileAttributes                          ;是否是文件夹
    jz notdirc                                               ;不是文件夹
    invoke GetCurrentDirectory,1023,addr szCurDir
    invoke StdOut,offset szCurDir
    lea eax,fdata.cFileName
    invoke StdOut,eax
    invoke StdOut,offset szCrLf
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;   递归核心部分
    invoke StdOut,offset buffer
    ;尽量在调用后改寄存器的值
    mov edx,offset buffer
    lea ecx,fdata.cFileName
    mov ebx,0
  loopstrcpy:
    mov al,[ecx+ebx]
    mov [edx+ebx],al
    inc ebx
    or al,al
    jnz loopstrcpy
    invoke StdOut,offset buffer
    invoke serch,offset buffer
    invoke SetCurrentDirectory,offset uppath
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    jmp findloop
notdirc:
    nop
    jmp findloop
return:
     invoke CloseHandle,hFind
    mov eax,0
    ret
  
serch endP
exitme:  
    ;暂停显示,回车键关闭
    invoke StdOut,CTXT(0dh,0ah,'这种地方要加上提示 比如按回车键退出神马的',0dh,0ah)
    invoke StdIn,addr buffer,sizeof buffer
    invoke ExitProcess,0
  
end START



#15
zklhp2012-07-13 12:55
看了半天核心问题没看出来

   lea eax,fdata.cFileName
    mov ebx,0
  loopstrcpy:
    mov al,[eax+ebx]
    mov [edx+ebx],al
    inc ebx
    or al,al
    jnz loopstrcpy

你又用eax做指针 又用他转字符串 怎么可能正常 我能把他改成不出错真是厉害啊 关键问题没改出来 改其他的没用

总的来说 楼主的程序写的还是不错的

加油哦 顺便记得结题给分


[ 本帖最后由 zklhp 于 2012-7-13 12:56 编辑 ]
#16
C_printf2012-07-13 14:08
回复 15楼 zklhp
程序代码:
;MASMPlus 代码模板 - 控制台程序

.386
.model flat, stdcall
option casemap :none

include windows.inc
include user32.inc
include kernel32.inc
include masm32.inc
include gdi32.inc

includelib gdi32.lib
includelib user32.lib
includelib kernel32.lib
includelib masm32.lib
include macro.asm

 serch PROTO :DWORD                   ;申明过程
    ;.stack
    .data
    despath db 'D:\\',0                        ; 要搜索的路径
    findtype db '*.*',0                       
    uppath  db  '..',0
    szCurDir db 1024 dup(0)                    
    endstr db '$'
    szFullNmae db 1024 dup(0)
    lpMsg        db 1024 dup(0),0
.data?
    buffer    db MAX_PATH dup(?)
   
.CODE
START:

     invoke serch,addr despath                 ;启动过程

    jmp exitme

serch proc     szPath    :DWORD  ;过程定义
      
        local fdata        :WIN32_FIND_DATA
        local hFind        :HANDLE

    invoke SetCurrentDirectory,szPath ;设置当前工作目录
    or eax,eax
    jz return
    invoke FindFirstFile,addr findtype,addr fdata          ;查找文件开始
    mov hFind,eax
findloop:
    invoke FindNextFile,hFind,addr fdata       ;循环搜索当前目录的文件
    or eax,eax
    jz return
    mov al, fdata.cFileName
    cmp al,'.'
    jz findloop                                             ; 如果 是'.'或者是'..'就continue  我只判断第一个字符
    mov eax,FILE_ATTRIBUTE_DIRECTORY
    and eax,fdata.dwFileAttributes                          ;是否是文件夹
    jz notdirc                                                            ;不是文件夹
   
    invoke GetCurrentDirectory,1023,addr szCurDir
    invoke StdOut,CTXT('[')
    invoke StdOut,offset szCurDir
    invoke StdOut,CTXT(']')
     lea eax,fdata.cFileName
    invoke StdOut,eax
    invoke StdOut,CTXT(0dh,0ah)
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;   递归核心部分
    mov edi,offset lpMsg
    lea esi,fdata.cFileName
    mov ebx,0
    cld
  loopstrcpy:
       lodsb
       stosb
    or al,al
    jnz loopstrcpy
    invoke serch,addr lpMsg
    invoke SetCurrentDirectory,offset uppath

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    jmp findloop
notdirc:
    jmp findloop
return:
     invoke CloseHandle,hFind
    mov eax,0
    ret
   
serch endP
exitme:   
    ;暂停显示,回车键关闭
    invoke StdOut,CTXT(0dh,0ah,'这种地方要加上提示 比如按回车键退出神马的',0dh,0ah)
    invoke StdIn,addr buffer,sizeof buffer
    invoke ExitProcess,0
   
end START
搞定了!哈哈,感谢你!其实非递归没什么难度 ,难的是递归地址的保护。。。
#17
C_printf2012-07-13 14:15
回复 15楼 zklhp
顺便问一句,这MASMplus没有断点调试吗?  debug能调 但是调的不是我写的代码。。。。
#18
zklhp2012-07-13 14:36
MasmPlus作者原来说要在新版里加调试功能 不过现在他自己都放弃开发新版了。。。

对于汇编 加断点很容易 int 3h 会激活系统设置的调试器

其实对于汇编 IDE内置调试功能不重要 因为很多调试器能进行汇编级别的调试 选一个你用的顺手的就可以了
#19
zklhp2012-07-13 14:38
你别说这个程序简单 要写好还真不容易呢 牵扯的东西很多 能写出来运行没错只是最基本的

继续努力罢 祝你成功
#20
C_printf2012-07-13 15:27
回复 19楼 zklhp
。。。
#21
信箱有效2012-07-13 16:05
楼主的代码不象新手呀。我啥时候才能写出这样的呢
1