首页
社区
课程
招聘
[原创]汇编实现 类strrchr 函数功能,遇到迷惑
2008-11-24 14:13 10280

[原创]汇编实现 类strrchr 函数功能,遇到迷惑

2008-11-24 14:13
10280
_Strrchr        proc        uses        edi ecx ebx
;                jmp        @f
                invoke        lstrlen,offset szPath
                lea        ebx,offset szPath
                add        ebx,eax
                std
                mov        edi, ebx
                mov        ecx,eax
                mov        al,5ch
                repne scasb
                inc        edi
                xor        eax,eax
                mov        [edi], al
;@@:
;                invoke        MessageBox,NULL,offset szPath,offset szCaptionMain,MB_OK
                ret
_Strrchr        endp

没有参数,直接使用全局变量

用OLLYDBG调试反汇编代码是这样的

004011E9  /$  57            push    edi
004011EA  |.  51            push    ecx
004011EB  |.  53            push    ebx
004011EC  |.  68 08304000   push    00403008                         ; /String = ""
004011F1  |.  E8 3E010000   call    <jmp.&KERNEL32.lstrlenA>         ; \lstrlenA
004011F6  |.  8D1D 08304000 lea     ebx, dword ptr [403008]
004011FC  |.  03D8          add     ebx, eax
004011FE  |.  FD            std
004011FF  |.  8BFB          mov     edi, ebx
00401201  |.  8BC8          mov     ecx, eax
00401203  |.  B0 5C         mov     al, 5C
00401205  |.  F2:AE         repne   scas byte ptr es:[edi]
00401207  |.  47            inc     edi
00401208  |.  33C0          xor     eax, eax
0040120A  |.  6A 00         push    0                                ; /Style = MB_OK|MB_APPLMODAL
0040120C  |.  68 99204000   push    00402099                         ; |Title = "GuardianServerMate"
00401211  |.  68 08304000   push    00403008                         ; |Text = ""
00401216  |.  6A 00         push    0                                ; |hOwner = NULL
00401218  |.  E8 B1000000   call    <jmp.&USER32.MessageBoxA>        ; \MessageBoxA
0040121D  |.  5B            pop     ebx
0040121E  |.  59            pop     ecx
0040121F  |.  5F            pop     edi
00401220  \.  C3            retn

直接执行程序就报错退出,"0x77efaaa6" 指令引用的"0x00000044"内存.该内存不能为"written"
但是调试器可以正常运行程序!
要是去掉上面一段代码程序运行正常!

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
点赞7
打赏
分享
最新回复 (29)
雪    币: 2108
活跃值: (21)
能力值: (RANK:260 )
在线值:
发帖
回帖
粉丝
书呆彭 6 2008-11-24 14:26
2
0
在调试器不不要选择忽略内存异常,然后再运行

确定是哪条指令引起的异常,才好进行分析
雪    币: 214
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
llac 2008-11-24 14:39
3
0
暂停在ntdll 里面的
7C93B1FA上,下步不知道怎么操作了,多谢指教,下面是抓的暂停函数反汇编代码

7C93B19F >  8BFF            mov     edi, edi
7C93B1A1    55              push    ebp
7C93B1A2    8BEC            mov     ebp, esp
7C93B1A4    83EC 68         sub     esp, 68
7C93B1A7    53              push    ebx
7C93B1A8    56              push    esi
7C93B1A9    8B75 08         mov     esi, dword ptr [ebp+8]
7C93B1AC    33DB            xor     ebx, ebx
7C93B1AE    81FE 78B1997C   cmp     esi, 7C99B178
7C93B1B4    895D F8         mov     dword ptr [ebp-8], ebx
7C93B1B7    0F9445 0B       sete    byte ptr [ebp+B]
7C93B1BB    64:A1 18000000  mov     eax, dword ptr fs:[18]
7C93B1C1    0FB64D 0B       movzx   ecx, byte ptr [ebp+B]
7C93B1C5    8988 840F0000   mov     dword ptr [eax+F84], ecx
7C93B1CB    381D C4B0997C   cmp     byte ptr [7C99B0C4], bl
7C93B1D1  ^ 0F85 0C89FFFF   jnz     7C933AE3
7C93B1D7    A0 E8B1997C     mov     al, byte ptr [7C99B1E8]
7C93B1DC    F6D8            neg     al
7C93B1DE    57              push    edi
7C93B1DF    1BC0            sbb     eax, eax
7C93B1E1    F7D0            not     eax
7C93B1E3    25 E0B1997C     and     eax, 7C99B1E0
7C93B1E8    8BF8            mov     edi, eax
7C93B1EA    8B46 10         mov     eax, dword ptr [esi+10]
7C93B1ED    3BC3            cmp     eax, ebx
7C93B1EF    8945 FC         mov     dword ptr [ebp-4], eax
7C93B1F2    0F84 9E000000   je      7C93B296
7C93B1F8    8B06            mov     eax, dword ptr [esi]
7C93B1FA    FF40 10         inc     dword ptr [eax+10]
7C93B1FD    8B45 FC         mov     eax, dword ptr [ebp-4]
7C93B200    83E0 01         and     eax, 1
7C93B203    8945 E8         mov     dword ptr [ebp-18], eax
7C93B206    8B06            mov     eax, dword ptr [esi]
7C93B208    FF40 14         inc     dword ptr [eax+14]
7C93B20B    F605 F002FE7F 0>test    byte ptr [7FFE02F0], 1
7C93B212    0F85 2E690200   jnz     7C961B46
7C93B218    395D E8         cmp     dword ptr [ebp-18], ebx
7C93B21B    57              push    edi
7C93B21C    53              push    ebx
7C93B21D    0F85 E8840100   jnz     7C95370B
7C93B223    FF75 FC         push    dword ptr [ebp-4]
7C93B226    E8 052DFFFF     call    ZwWaitForSingleObject
7C93B22B    3D 02010000     cmp     eax, 102
7C93B230    0F84 9B690200   je      7C961BD1
7C93B236    3BC3            cmp     eax, ebx
7C93B238    0F8C 506A0200   jl      7C961C8E
7C93B23E    385D 0B         cmp     byte ptr [ebp+B], bl
7C93B241    5F              pop     edi
7C93B242    74 18           je      short 7C93B25C
7C93B244    64:A1 18000000  mov     eax, dword ptr fs:[18]
7C93B24A    8B40 24         mov     eax, dword ptr [eax+24]
7C93B24D    8946 0C         mov     dword ptr [esi+C], eax
7C93B250    64:A1 18000000  mov     eax, dword ptr fs:[18]
7C93B256    8998 840F0000   mov     dword ptr [eax+F84], ebx
7C93B25C    5E              pop     esi
7C93B25D    5B              pop     ebx
7C93B25E    C9              leave
7C93B25F    C2 0400         retn    4
雪    币: 214
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
llac 2008-11-24 14:40
4
0
有点疑惑的是,怎么会暂停在系统代码上呢
雪    币: 2108
活跃值: (21)
能力值: (RANK:260 )
在线值:
发帖
回帖
粉丝
书呆彭 6 2008-11-24 14:52
5
0
如果你全部程序就只有人贴出来那些的话,可能是在MessageBoxA发生的异常。

因为你整个过程只调用了两个系统API,但lstrlenA是在kernel32.dll中直接计算的,不进入ntdll.dll,所以检查一下是不是MessageBoxA内部发生的异常。

只需要F8步过  00401218  |.  E8 B1000000   call    <jmp.&USER32.MessageBoxA>        ; \MessageBoxA

看是不发生异常。
雪    币: 723
活跃值: (81)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
mik 4 2008-11-24 15:48
6
0
你的是程序逻辑搞错了。
我帮你转化C来看,容易看些:

这是你的逻辑:

void _strchr(char *s, char c)
{
int len = strlen(s);
char *d = s + len;

while ((*d-- != c) || len--) ;

d++;
*d = c;

Messagebox(NULL, s , offset szCaptionMain,MB_OK);
}


看出问题了吧:

假如: s = "a";
那么: d = s + 1;  这是一个 '\0' 字节的位置
经过 while(); 之后 d 停留在 '\a';
然后 d++ 又停留在 '\0'
然后写 al 到 '\0' 的位置上
雪    币: 214
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
llac 2008-11-24 22:07
7
0
谢谢你们,其实我的思路是处理一个路径字符串,假设有这么一个串E:\Games\浩方对战平台
那么执行我上面代码后应该是E:\Games 对吧,但是执行就报错!逻辑有错么!
雪    币: 214
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
llac 2008-11-24 22:17
8
0
olldbg跟踪,停在系统代码GDI32里,报"0x77efaaa6" 指令引用的"0x00000044"内存.该内存不能为"written"不知怎么调试了
但是注释掉
_Strrchr  proc  uses  edi ecx ebx
;    jmp  @f
    invoke  lstrlen,offset szPath
    lea  ebx,offset szPath
    add  ebx,eax
    std
    mov  edi, ebx
    mov  ecx,eax
    mov  al,5ch
    repne scasb
    inc  edi
    xor  eax,eax
    mov  [edi], al
;@@:
;    invoke  MessageBox,NULL,offset szPath,offset szCaptionMain,MB_OK
    ret
_Strrchr  endp
这段代码就正常,其实这段代码就 lstrlen 我用了系统的!
雪    币: 214
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
llac 2008-11-24 22:27
9
0
完整程序是这样的,用ollydbg调试忽略内存异常发现一个奇怪的现象!
.586
.model flat,stdcall
option casemap:none

include                windows.inc
include                user32.inc
includelib                user32.lib
include                kernel32.inc
includelib                kernel32.lib
include                shlwapi.inc
includelib                shlwapi.lib

ID_TIMER                equ        1
IDI_GUARDIAN        equ        1

.data?

hInstance                        dd        ?
hWndMain                dd        ?
szPath                        db        [MAX_PATH] dup (?)
szTmp                        db        [MAX_PATH] dup(?)
.const

szClassName                db        'Guardian',0
szCaptionMain        db        'GuardianServerMate',0
szText                        db        '守护程序!',0
szMutexText                db        'ServerMate',0
szExecuteName        db        'ServerMate.exe',0
szAddText                db        '\ServerMate.exe',0
szInfoText                db        '程序不完整,要启动吗?',0

.code

_ProcWinMain        proc        uses ebx edi esi,hWnd,uMsg,wParam,lParam
                local        @stPs:PAINTSTRUCT
                local        @stRect:RECT
                local        @hDc
                local        @hMutex:HANDLE
                local        @stInfo
                local        @pInfo:PROCESS_INFORMATION

                mov        eax,uMsg
                .if        eax ==        WM_TIMER
                        invoke        CreateMutex,NULL,FALSE,offset szMutexText
                        mov        ebx,eax
                        invoke        GetLastError
                        .if eax == ERROR_ALREADY_EXISTS
                            invoke CloseHandle,ebx
                            invoke GetStartupInfo,addr @stInfo
                            invoke CreateProcess,offset szExecuteName,NULL,NULL,NULL,NULL,\
                                   NORMAL_PRIORITY_CLASS,NULL,NULL,addr @stInfo,addr @pInfo
                        .endif
                .elseif        eax ==        WM_PAINT
                        invoke        BeginPaint,hWnd,addr @stPs
                        mov        @hDc,eax

                        invoke        GetClientRect,hWnd,addr @stRect
                        invoke        DrawText,@hDc,offset szText,-1,addr @stRect,\
                                DT_SINGLELINE or DT_CENTER or DT_VCENTER
                        invoke        EndPaint,hWnd,addr @stPs
                .elseif        eax ==        WM_CLOSE
                        invoke        DestroyWindow,hWnd
                        invoke        KillTimer,hWnd,ID_TIMER
                        invoke        PostQuitMessage,NULL
                .else       
                        invoke        DefWindowProc,hWnd,uMsg,wParam,lParam
                        ret
                .endif
                xor        eax,eax
                ret
_ProcWinMain        endp

_WinMain        proc
                local        @stWndClass:WNDCLASSEX
                local        @stMsg:MSG

                invoke        GetModuleHandle,NULL
                mov        hInstance,eax
                invoke        RtlZeroMemory,addr @stWndClass,sizeof @stWndClass
;                ---------------------------------------------
;                                注册窗口
;                ---------------------------------------------
                invoke        LoadCursor,0,IDC_ARROW
                mov        @stWndClass.hCursor,eax
                push        hInstance
                pop        @stWndClass.hInstance
                mov        @stWndClass.cbSize,sizeof WNDCLASSEX
                mov        @stWndClass.style,CS_HREDRAW or CS_VREDRAW
                mov        @stWndClass.lpfnWndProc,offset _ProcWinMain
                mov        @stWndClass.hbrBackground,COLOR_WINDOW + 1
                mov        @stWndClass.lpszClassName,offset szClassName
                invoke        LoadIcon,hInstance,IDI_GUARDIAN
                mov        @stWndClass.hIcon,eax
                mov        @stWndClass.hIconSm,eax
                invoke        RegisterClassEx,addr @stWndClass
;                ---------------------------------------------
;                                创建窗口
;                ---------------------------------------------
                invoke        CreateWindowEx,WS_EX_CLIENTEDGE,offset szClassName,offset szCaptionMain,\
                        WS_OVERLAPPEDWINDOW,100,100,600,400,NULL,NULL,hInstance,NULL
                mov        hWndMain,eax
                invoke        SetTimer,hWndMain,ID_TIMER,1000,NULL
                invoke        ShowWindow,hWndMain,SW_SHOWNORMAL
                invoke        UpdateWindow,hWndMain

                .while        TRUE
                        invoke        GetMessage,addr @stMsg,NULL,0,0
                        .break        .if eax == 0
                        invoke        TranslateMessage,addr @stMsg
                        invoke        DispatchMessage,addr @stMsg
                .endw
                ret
_WinMain        endp

_Strrchr        proc        uses        edi ecx ebx
;                jmp        @f
                invoke        lstrlen,offset szPath
                lea        ebx,offset szPath
                add        ebx,eax
                std
                mov        edi, ebx
                mov        ecx,eax
                mov        al,5ch
                repne scasb
                inc        edi
                xor        eax,eax
                mov        [edi], al
;@@:
;                invoke        MessageBox,NULL,offset szPath,offset szCaptionMain,MB_OK
                ret
_Strrchr        endp

_PreProc        proc
                invoke        GetModuleFileName,NULL,offset szPath,MAX_PATH
                call        _Strrchr
;前面执行正常截断字符串,但是下面API调用过后,字符串却是一个莫名其妙的值...!
                invoke        lstrcat,offset szPath,offset szAddText
;                invoke        MessageBox,NULL,offset szPath,offset szCaptionMain,MB_OK
                invoke PathFileExists,offset szPath
                .if !eax
                        invoke MessageBox,NULL,offset szInfoText,offset szCaptionMain,MB_OKCANCEL
                        .if eax != 1
                                invoke        ExitProcess,NULL
                        .endif
                .endif
                ret
_PreProc                endp

start:
                call        _PreProc
                call        _WinMain
                invoke        ExitProcess,NULL
                end        start
雪    币: 723
活跃值: (81)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
mik 4 2008-11-24 22:38
10
0
我就真搞不懂,为什么要用 masm32  来写程序,

既然一定要用 masm32 来写,但却是 C 的思维逻辑和编程模式来实现汇编

既然这样为什么不用 C 来写,既容易写又容易明白。

我个人认为,用 masm32 而不用 c 来写,这不是展示汇编能力的地方,个人对看这样的代码真的不感兴趣
雪    币: 214
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
llac 2008-11-24 22:56
11
0
其实也不是非要用masm32来写,想熟悉下API方式的编程,感觉汇编在这方面更能展示系统运行细节,同时也想复习一下汇编知识,仅此而已
望mik别见怪,谢谢你的回复
雪    币: 214
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
llac 2008-11-24 23:02
12
0
其实上面这个程序我用C已经写好了,功能正常没有问题!就是想翻译成汇编,但是汇编没有C库函数strrchr,而API也没这样一个功能的函数!
自己实现的时候就出错了!
雪    币: 723
活跃值: (81)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
mik 4 2008-11-24 23:03
13
0
真要用汇编来写,那就要用汇编思维呀。

用汇编写而按C的思维逻辑和模式写,个人认为这应该要避免的。
雪    币: 723
活跃值: (81)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
mik 4 2008-11-24 23:04
14
0
你把你的C版本贴出来,我帮你写成汇编的
雪    币: 214
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
llac 2008-11-24 23:15
15
0
// Guardian.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "resource.h"
#include "shlwapi.h"

#pragma  comment(lib,"Shlwapi.lib")

#define ID_TIMER 1

// Global Variables:
HINSTANCE hInst;
HWND hWnd;

// Foward declarations of functions included in this code module:
ATOM                                MyRegisterClass(HINSTANCE hInstance);
BOOL                                InitInstance(HINSTANCE, int);
LRESULT CALLBACK        WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK        About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
        MSG msg;
        TCHAR szPath[MAX_PATH];

        MyRegisterClass(hInstance);
        if (!InitInstance (hInstance, nCmdShow))
        {
                return FALSE;
        }

        GetModuleFileName( NULL , szPath , MAX_PATH );   
        *strrchr( szPath,'\\') = NULL;   
        strcat( szPath, "\\ServerMate.exe");
        if(!PathFileExists(szPath))
                if(1 != MessageBox(hWnd,"程序不完整,要启动吗?","提示",MB_OKCANCEL))
                {
                        return FALSE;
                }

        while (GetMessage(&msg, NULL, 0, 0))
        {
                        TranslateMessage(&msg);
                        DispatchMessage(&msg);
        }

        return msg.wParam;
}

ATOM MyRegisterClass(HINSTANCE hInstance)
{
        WNDCLASSEX wcex;

        wcex.cbSize = sizeof(WNDCLASSEX);

        wcex.style                        = CS_HREDRAW | CS_VREDRAW;
        wcex.lpfnWndProc        = (WNDPROC)WndProc;
        wcex.cbClsExtra                = 0;
        wcex.cbWndExtra                = 0;
        wcex.hInstance                = hInstance;
        wcex.hIcon                        = LoadIcon(hInstance, (LPCTSTR)IDI_GUARDIAN);
        wcex.hCursor                = LoadCursor(NULL, IDC_ARROW);
        wcex.hbrBackground        = (HBRUSH)(COLOR_WINDOW+1);
        wcex.lpszMenuName        = NULL;
        wcex.lpszClassName        = "GUARDIAN";
        wcex.hIconSm                = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_GUARDIAN);

        return RegisterClassEx(&wcex);
}

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{

   hInst = hInstance; // Store instance handle in our global variable

   hWnd = CreateWindow("GUARDIAN","ServerMateGuardian", WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if (!hWnd)
   {
      return FALSE;
   }
   SetTimer(hWnd,ID_TIMER,1000,NULL);
   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
        HANDLE hMutex;
        STARTUPINFO stinfo;
        PROCESS_INFORMATION pinfo;
        int wmId, wmEvent;
        PAINTSTRUCT ps;
        HDC hdc;

        switch (message)
        {
                case WM_TIMER:
                        hMutex = CreateMutex(NULL, FALSE, "ServerMate");
                        if (GetLastError() == ERROR_ALREADY_EXISTS) {
                                CloseHandle(hMutex);
                                GetStartupInfo(&stinfo);
                                CreateProcess("ServerMate.exe",NULL,NULL,NULL,NULL,
                                                                NORMAL_PRIORITY_CLASS,NULL,NULL,&stinfo,&pinfo);
                                hMutex = NULL;
                        }
                        break;
                case WM_COMMAND:
                        wmId    = LOWORD(wParam);
                        wmEvent = HIWORD(wParam);
                        // Parse the menu selections:
                        break;
                case WM_PAINT:
                        hdc = BeginPaint(hWnd, &ps);
                        // TODO: Add any drawing code here...
                        RECT rt;
                        GetClientRect(hWnd, &rt);
                        DrawText(hdc, "szHello", strlen("szHello"), &rt, DT_CENTER);
                        EndPaint(hWnd, &ps);
                        break;
                case WM_DESTROY:
                        KillTimer (hWnd,ID_TIMER);
                        PostQuitMessage(0);
                        break;
                default:
                        return DefWindowProc(hWnd, message, wParam, lParam);
   }
   return 0;
}

这是C版本的
雪    币: 723
活跃值: (81)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
mik 4 2008-11-24 23:28
16
0
我是说汇编实现strrchr()
你上面这个程序,我已经说了没必要用汇编写
雪    币: 214
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
llac 2008-11-24 23:44
17
0
  恩,只是我不知道为什么汇编写的哪个会报错,调试找不到思路
OD开忽略内存异常,调试一切正常,不开忽略异常,一加载程序就挂了
雪    币: 2108
活跃值: (21)
能力值: (RANK:260 )
在线值:
发帖
回帖
粉丝
书呆彭 6 2008-11-24 23:52
18
0
晕死,把话听岔了。。

mik的意思是说你把自己写的strrchr()的C代码贴出来,帮你用汇编表达一下。。。

你理解错mik的意思了。。。
雪    币: 723
活跃值: (81)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
mik 4 2008-11-24 23:55
19
0
char * strrchr(const char *s, char c)

--------------------------------------------------

比较正统的汇编版:

__strrchr:
       push ebp
       mov ebp, esp

       mov    edi,  [ebp+8]                        ; char *s
       movzx ebx, byte ptr [ebp+0x0c]          ; char c

       xor eax, eax

ll:
       movzx edx,  byte ptr [edi]
       test edx, edx
       jz done

       cmp edx, ebx
       jnz lll
      
       mov eax, edi

lll:
       inc edi
       jmp ll

done:
       mov esp, ebp
       pop ebp

       ret
雪    币: 723
活跃值: (81)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
mik 4 2008-11-24 23:58
20
0
欢迎测试一下,C 版的 strrchr() 和我上面写的 __strrchr()

我上面用汇编写的__strrchr() 虽然不那么好看有几条jmp,但感觉效果应该挺高的
雪    币: 214
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
llac 2008-11-25 00:01
21
0
谢谢mik,我加进去测试一下
其实我偷了个懒直接用下面代码,来实现截断字符串的功能!
_Strrchr  proc  uses  edi ecx ebx
    invoke  lstrlen,offset szPath
    lea  ebx,offset szPath
    add  ebx,eax
    std
    mov  edi, ebx
    mov  ecx,eax
    mov  al,5ch
    repne scasb
    inc  edi
    xor  eax,eax
    mov  [edi], al
    ret
_Strrchr  endp
雪    币: 214
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
llac 2008-11-25 00:09
22
0
mik 你这代码是找到字串s里第一个和c相等的位置吧
雪    币: 723
活跃值: (81)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
mik 4 2008-11-25 00:30
23
0
char *my_strrchr(const char *s, char c)
{

__asm {
mov edi, [ebp+8] ; char *s
movzx ebx, byte ptr [ebp+0xc] ; char c

xor eax, eax

ll:
movzx edx, byte ptr [edi]
test edx, edx
jz done

cmp edx, ebx
jnz lll

mov eax, edi

lll:
inc edi
jmp ll

done:

}

}



void test()
{

LARGE_INTEGER l,start,end;


double interval;
double freq;

QueryPerformanceFrequency(&l);
freq = (double)l.QuadPart;


int i = 0;
char *p = 0;
char *s = "mikik";


QueryPerformanceCounter(&start);

for (i = 0; i < 10000000u; i++)
p = strrchr(s, 'i');

QueryPerformanceCounter(&end);

printf("%c at %x\n",'i',p);

interval = (double)(end.QuadPart - start.QuadPart);

printf("strrchr(): time is: %g ms\n", interval*1000/freq);



///////////////////////////////////////////////////////////////////////////////////


QueryPerformanceCounter(&start);

for (i = 0; i < 10000000u; i++)
p = my_strrchr(s, 'i');


QueryPerformanceCounter(&end);

printf("%c at %x\n",'i',p);


interval = (double)(end.QuadPart - start.QuadPart);

printf("my_strrchr(): time is: %g ms\n", interval*1000/freq);

}


贴出我的测试结果:

i at f3574f
strrchr(): time is: 672.535 ms

i at f3574f
my_strrchr(): time is: 432.899 ms

我上面写的 my_strrchr() 比系统的 strrchr() 快多了。 哈哈哈
雪    币: 723
活跃值: (81)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
mik 4 2008-11-25 00:33
24
0
LZ:我贴出来的 my_strrchr() 版本,是用汇编语言的思维逻辑写的,而不是 C 思维逻辑。

比系统提供的 strrchr() 还要快。

所以,一定要注意思维逻辑 
雪    币: 723
活跃值: (81)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
mik 4 2008-11-25 00:36
25
0
结果是正确的,你好好领会吧。
游客
登录 | 注册 方可回帖
返回