2

我正在使用以下 ASM 例程对数组进行冒泡排序。我想知道我的代码效率低下:

.386
.model flat, c
option casemap:none


.code
            public sample
            sample PROC
            ;[ebp+0Ch]Length
            ;[ebp+08h]Array
                            push ebp
                            mov ebp, esp
                            push ecx
                            push edx
                            push esi
                            push eax
                            mov ecx,[ebp+0Ch]
                            mov esi,[ebp+08h]
                _bubbleSort:
                            push ecx
                            push esi
                            cmp ecx,1
                            je _exitLoop
                            sub ecx,01h
                            _miniLoop:
                                        push ecx
                                        mov edx,DWORD PTR [esi+4]
                                        cmp DWORD PTR [esi],edx
                                        ja _swap
                                        jmp _continueLoop
                            _swap:      
                                        lodsd
                                        mov DWORD PTR [esi-4],edx
                                        xchg DWORD PTR [esi],eax    
                                        jmp _skipIncrementESI
                            _continueLoop:
                                        add esi,4
                            _skipIncrementESI:
                                        pop ecx
                                        loop _miniLoop 
                            _exitLoop:
                            pop esi
                            pop ecx 
                            loop _bubbleSort
                            pop eax
                            pop esi
                            pop edx
                            pop ecx
                            pop ebp
                            ret 
            sample ENDP
            END 

基本上我有两个循环,就像冒泡排序算法一样。外循环的 ecx 值为 10,内循环的值为 [ecx-1]。我已经尝试过该例程,它编译并运行成功,但我不确定它是否有效。

4

3 回答 3

3

你可以做几件事来加速你的汇编代码:

  • 不要做类似的事情ja label_1 ; jmp label_2。就做吧jbe label_2

  • loop是一个非常慢的指令。dec ebx; jnz loopstart快得多

  • 使用所有寄存器而不是重复推送/弹出 ecx 和 esi。用ebxedi

  • jmp-targets 应该很好地对齐。align 4在两个循环开始之前和之后使用jbe

从 Intel 为您的 cpu 获取手册(您可以将其下载为 pdf 格式),其中包含操作码的时间安排,也许它还有其他提示。

于 2011-10-09T23:00:38.043 回答
2

几个简单的提示:

1)尽量减少条件跳转的次数,因为它们非常昂贵。如果可能,展开。2) 重新排序指令以最小化由于数据依赖而导致的停顿:

cmp DWORD PTR [esi],edx ;// takes some time to compute,
mov edx,DWORD PTR [esi+4] ; 
ja _swap ;// waits for results of cmp

3) 避免旧的复合指令(dec, jnzpair 比注册更快loop且不受约束ecx

编写比优化 C 编译器生成的代码更快的汇编代码是相当困难的,因为您应该考虑很多因素:数据和指令缓存的大小、对齐、流水线、指令时序。你可以在这里找到一些很好的文档。特别推荐第一本书:Optimizing software in C++

于 2011-10-09T23:21:01.870 回答
0

如果我们不需要此指令的标志,请替换“add esi,4”:

_continueLoop:
            lea esi,[esi+4]
于 2014-01-29T06:13:21.750 回答