首页 文章

在装配中找到平均值,最小值和最大值

提问于
浏览
2

我在使用汇编语言查找数组的平均值,最小值和最大值时遇到问题 . 我用C创建了一个简单的数组,并创建了一个test.asm文件来传递它 . 我想出了平均值,但现在它的最小值和最大值似乎无法弄清楚 .

#include <iostream>
using namespace std;

extern "C"
int test(int*, int);

int main()
{
const int SIZE = 7;
int arr[SIZE] = { 1,2,3,4,5,6,7 };

int val = test(arr, SIZE);


cout << "The function test returned: " << val << endl;

return 0;
}

这是我的test.asm,它添加了所有值并返回4 .

.686
.model flat

.code


_test PROC ;named _test because C automatically prepends an underscode, it is needed to interoperate
push ebp
mov ebp,esp ;stack pointer to ebp

mov ebx,[ebp+8] ; address of first array element
mov ecx,[ebp+12]
mov ebp,0
mov edx,0
mov eax,0


loopMe:
cmp ebp,ecx
je allDone


add eax,[ebx+edx]
add edx,4
add ebp,1
jmp loopMe

allDone:
mov edx,0
div ecx

pop ebp
ret
_test ENDP

END

我仍然试图找出如何找到min,因为max将以类似的方式完成 . 我假设您使用cmp来比较值,但到目前为止我尝试的所有内容都没有成功 . 我对汇编语言很新,我很难掌握 . 任何帮助表示赞赏 .

1 回答

  • 1

    感谢任何帮助

    好的,所以我会告诉你重构的平均功能,即使你没有直接要求它 . :)

    你可以从中学到的东西:

    • 简化函数序言/结尾,当 ebp 未在代码中修改时

    • 输入数组的值为32b int ,所以为了得到正确的平均值,你应该计算64b和,并做64b和和

    • 细微"tricks"如何获取零值( xor )或 inc 如何为1(降低代码大小)

    • 通过返回假平均 0 处理零大小的数组(没有崩溃)

    • 添加了由32b寄存器/指令组成的两个64b值

    • 计算人"index"(1 =>直接cmp, size 可能),但解决32b值(在寻址中使用 *4

    • 重命名为 getAverage

    顺便说一下,这并没有针对性能进行优化,我试图保持源“简单”,因此很容易阅读和理解它在做什么 .

    _getAverage PROC
        ; avoiding `ebp` usage, so no need to save/set it
        mov   ebx,[esp+4]   ; address of first array element
        mov   ecx,[esp+8]   ; size of array
        xor   esi,esi       ; array index 0
        ; 64b sum (edx:eax) = 0
        xor   eax,eax
        cdq
        ; test for invalid input (zero sized array)
        jecxz zeroSizeArray ; arguments validation, returns 0 for 0 size
    
        ; here "0 < size", so no "index < size" test needed for first element
        ; "do { ... } while(index < size);" loop variant
    
    sumLoop:
        ; extend value from array[esi] to 64b (edi is upper 32b)
        mov   edi,[ebx+esi*4]
        sar   edi,31
        ; edx:eax += edi:array[esi]  (64b array value added to 64b sum)
        add   eax,[ebx+esi*4]
        adc   edx,edi
        ; next index and loop while index < size
        inc   esi
        cmp   esi,ecx
        jb    sumLoop
    
        ; divide the 64b sum of integers by "size" to get average value
        idiv  ecx           ; signed (!) division (input array is signed "int")
        ; can't overflow (Divide-error), as the sum value was accumulated
        ; from 32b values only, so EAX contains full correct result
    zeroSizeArray:
        ret
    _getAverage ENDP
    

相关问题