无心人 发表于 2009-2-4 20:42:34

?

帖子呢?

gxqcn 发表于 2009-2-4 20:44:06

mathe 的代码体现了一种算法思路,
最终的机器代码当然是可以避免跳转的。

那如果是 64 位呢?:Q:

无心人 发表于 2009-2-4 20:53:32

:lol

我在10#给出了一个思路
MMX汇编
如果是64位的,应该还能用SSE
无跳转,无判断

gxqcn 发表于 2009-2-4 21:00:47

感觉还是尽量避免用MMX,
用SIMD指令因更高效,
因为这次不比上次的 UInt64x64To128() 那样需要反复拆包了。

无心人 发表于 2009-2-4 21:04:26

你怎么老排斥MMX啊

不支持 MMX的机器已经不存在了

liangbch 发表于 2009-2-4 21:06:06

我这里给出一个不是用 MMX和XMM指令的版本,使用跳表实现。因为VC中不可以定义标号的地址。故不得不使用汇编文件。
   在VC6.0,对于汇编文件,可以自定义build命令,在编译期间同时编译asm文件,为此,你需要
1。安装masm32
    2.在VC 中,设置 executable files 目录,指向ml.exe, 比如我的masm32 安装在 c:\masm32,因此executable files目录中添加 C:\masm32\BIN
   3. 在VC中,将asm文件添加到project.并选中那个asm文件,设置Custom Build
Commands 框填入:ml /coff /c $(InputPath)
outputs 框填入: $(InputName).obj
下面先给出cpp文件中的测试代码:extern "C" _fastcallint digLen(int n);
void digLenTest()
{
unsigned long n;

n=1;
printf("diglen(%u)=%d\n",n,digLen(n));
n=7;
printf("diglen(%u)=%d\n",n,digLen(n));

n=8;
printf("diglen(%u)=%d\n",n,digLen(n));
n=9;
printf("diglen(%u)=%d\n",n,digLen(n));
n=10;
printf("diglen(%u)=%d\n",n,digLen(n));
n=99;
printf("diglen(%u)=%d\n",n,digLen(n));

n=100;
printf("diglen(%u)=%d\n",n,digLen(n));
n=1000;
printf("diglen(%u)=%d\n",n,digLen(n));

n=9999;
printf("diglen(%u)=%d\n",n,digLen(n));
n=10000;
printf("diglen(%u)=%d\n",n,digLen(n));

n=99999;
printf("diglen(%u)=%d\n",n,digLen(n));
n=100000;
printf("diglen(%u)=%d\n",n,digLen(n));
}再给出汇编文件中的代码:
        .486P
        .387
        OPTION DOTNAME
_TEXT        SEGMENT DWORD PUBLIC FLAT 'CODE'
        ALIGN 004H
_TEXT        ENDS

_DATA        SEGMENT DWORD PUBLIC FLAT 'DATA'
        ALIGN 004H
_DATA        ENDS

_BSS        SEGMENT DWORD PUBLIC FLAT 'BSS'
        ALIGN 004H
_BSS        ENDS

_RDATA        SEGMENT DWORD PUBLIC FLAT 'DATA'
        ALIGN 004H
_RDATA        ENDS

_TEXT1        SEGMENT DWORD PUBLIC FLAT 'CODE'
        ALIGN 004H
_TEXT1        ENDS

_DATA1        SEGMENT DWORD PUBLIC FLAT 'DATA'
        ALIGN 004H
_DATA1        ENDS

        ASSUME        CS:FLAT,DS:FLAT,SS:FLAT
_DATA        SEGMENT DWORD PUBLIC FLAT 'DATA'
_DATA        ENDS


_TEXT        SEGMENT DWORD PUBLIC FLAT 'CODE'
    ALIGN   4
        PUBLIC @digLen@4

@digLen@4 PROC NEAR
        test        ecx, ecx
        jne        SHORT L919
        xor        eax, eax
        ret

L919:
        bsr eax,ecx
        jmp        DWORD PTR JTAB_1004

L_012:
        mov        eax, 1
        ret

L_3:
        cmp        ecx, 10                                       
        sbb        eax, eax
        add        eax, 2
        ret

L_45:
        mov        eax, 2
        ret

L_6:
        cmp        ecx, 100                               
        sbb        eax, eax
        add        eax, 3
        ret

L_78:
        mov        eax, 3
        ret

L_9:
        cmp        ecx, 1000                               
        sbb        eax, eax
        add        eax, 4
        ret

L936:
        mov        eax, 4
        ret

L938:
        cmp        ecx, 10000
        sbb        eax, eax
        add        eax, 5
        ret

L940:
        mov        eax, 5
        ret

L942:
        cmp        ecx, 100000
        sbb        eax, eax
        add        eax, 6
        ret

L944:
        mov        eax, 6
        ret

L946:
        cmp        ecx, 1000000
        sbb        eax, eax
        add        eax, 7
        ret

L948:
        mov        eax, 7
        ret

L950:
        cmp        ecx, 10000000
        sbb        eax, eax
        add        eax, 8
        ret
L952:
        mov        eax, 8
        ret

L954:
        cmp        ecx, 100000000                               
        sbb        eax, eax
        add        eax, 9
        ret

L956:
        mov        eax, 9
        ret

L958:
        cmp        ecx, 1000000000
        sbb        eax, eax
        add        eax, 10                                       
        ret

L960:
        mov        eax, 10                                       
        ret
       
        align 4
JTAB_1004:
        DD       L_012 ;0
        DD       L_012 ;1
        DD       L_012 ;2
       
        DD       L_3        ;3
       
        DD        L_45        ;4
        DD        L_45        ;5
       
        DD        L_6        ;6
               
        DD        L_78        ;7
        DD        L_78        ;8
       
        DD        L_9        ;9
       
        DD        L936        ;10
        DD        L936        ;11
        DD        L936        ;12
       
        DD        L938        ;13
       
        DD        L940        ;14
        DD        L940        ;15
       
        DD        L942        ;16
       
        DD        L944        ;17
        DD        L944        ;18
       
        DD        L946        ;19
       
        DD        L948        ;20
        DD        L948        ;21
        DD        L948        ;22
       
       
        DD        L950        ;23
       
        DD        L952        ;24
        DD        L952        ;25
       
        DD        L954        ;26
                       
        DD        L956        ;27
        DD        L956        ;28
       
        DD        L958        ;29
       
        DD        L960        ;30
        DD        L960        ;31
        ret        0

@digLen@4 ENDP
_TEXT        ENDS
END

无心人 发表于 2009-2-4 21:11:21

:L

   不懂

liangbch 发表于 2009-2-4 21:15:39

给你一段等价的C代码,你就明白了。

以上的汇编代码即为在编译器编译后的汇编代码的基础上优化(精简)而成.int log2(int n)
{
        _asm
        {
                mov ecx,n
                bsr eax,ecx
        }
}

extern "C"
_fastcall
int digLen(int n)
{
        if (n==0)
                return 0;

        int c=log2(n);
        switch (c)
        {
        case 0:
        case 1:
        case 2:
                return 1;
        case 3:
                if (n>=10)
                        return 2;
                else
                        return 1;
        case 4:
        case 5:
                return 2;
        case 6:
                if (n>=100)
                        return 3;
                else
                        return 2;
        case 7:
        case 8:
                return 3;
        case 9:
                if (n>=1000)
                        return 4;
                else
                        return 3;
        case 10:
        case 11:
        case 12:
                return 4;
       
        case 13:
                if (n>=10000)
                        return 5;
                else
                        return 4;

        case 14:
        case 15:
                return 5;

        case 16:
                if (n>=100000)
                        return 6;
                else
                        return 5;
        case 17:
        case 18:
                return 6;
        case 19:
                if (n>=1000000)
                        return 7;
                else
                        return 6;
        case 20:
        case 21:
        case 22:
                return 7;

        case 23:
                if (n>=10000000)
                        return 8;
                else
                        return 7;
        case 24:
        case 25:
                return 8;
        case 26:
                if (n>=100000000)
                        return 9;
                else
                        return 8;
        case 27:
        case 28:
                        return 9;
        case 29:
                        if (n>=1000000000)
                        return 10;
                else
                        return 9;
        case 30:
        case 31:
                return 10;
        }
}

无心人 发表于 2009-2-4 21:17:13

这么做也可以啊
    mov edx, n
    xor eax, eax
    cmp edx, 1   //1
    sbb ecx, ecx
    sub eax, ecx
    cmp edx, 10//2
    sbb ecx, ecx
    sub eax, ecx
    cmp edx, 100 //3
    sbb ecx, ecx
    sub eax, ecx
    cmp edx, 1000 //4
    sbb ecx, ecx
    sub eax, ecx
    cmp edx, 10000 //5
    sbb ecx, ecx
    sub eax, ecx
    cmp edx, 100000 //6
    sbb ecx, ecx
    sub eax, ecx
    cmp edx, 1000000 //7
    sbb ecx, ecx
    sub eax, ecx
    cmp edx, 10000000 //8
    sbb ecx, ecx
    sub eax, ecx
    cmp edx, 100000000 //9
    sbb ecx, ecx
    sub eax, ecx
    cmp edx, 1000000000 //10
    sbb ecx, ecx
    sub eax, ecx

gxqcn 发表于 2009-2-4 21:23:13

原帖由 无心人 于 2009-2-4 21:04 发表 http://bbs.emath.ac.cn/images/common/back.gif
你怎么老排斥MMX啊

不支持 MMX的机器已经不存在了

我不是排斥它,而是反感它需要 emms 来擦屁股。
另外用 SIMD 指令一次就可进行4组32位的比较,多么爽啊。:lol
页: 1 [2] 3 4 5 6 7
查看完整版本: 求一个无符号整数的10进制位数