assembly 如何在程序集中对两个数组元素求和?

jq6vz3qz  于 2022-11-13  发布在  其他
关注(0)|答案(1)|浏览(131)

(使用Visual Studio语法汇编代码)我知道这是一个显而易见的问题,但我对汇编还是个新手。
在下面的练习中,我很难理解esi寄存器是如何工作的:

#include <stdio.h>

int main()
{
    int a = 0;
    int b[5] = { 1, 2, 3, 4, 5 };
    int *c;

    c = &b[0];

    __asm {
        mov ebx, c 
        mov eax, dword ptr [ebx]
        mov esi, 3
        add eax, dword ptr [ebx+esi*4]
        mov ecx, eax
        mov a, ecx 
    }

    printf("sum of first and fourth element is: %d", a);
}

我需要打印第一个和第四个元素的总和。程序的工作原理如下:

  • 定义a和数组b,定义指针c,它指向b的第一个元素。
  • c移到ebx中。[ c指向第一个元素,因此ebx包含第一个元素]
  • 把指针指向的东西移到eax寄存器中。[它是ebx ]
  • 3移到esi寄存器中。[关键部分我不理解]
  • add运算符[我不理解关键部分]
  • 移动运算符[简单的部分,没有问题]

我的问题是:

  • 为什么我必须将3复制到esi寄存器中?
  • 为什么我必须执行此操作?[ebx+esi*4]

我知道esi使事情变得容易得多,但是我不知道如何使用这个寄存器。

vaqhlq81

vaqhlq811#

将数组b的第一个元素和第四个元素相加可写成:

int a = b[0] + b[3];

由于指针c被初始化为指向b的第一个元素,因此这等效于

int a = c[0] + c[3];

为了将c[3]与包含c值的ebx相加,代码将esi设置为3并使用add eax, dword ptr [ebx+esi*4]。此指令将从内存中读取的32位值与ebx在索引esi处指向的数组相加,然后直接乘以int的大小(作为寻址模式的一部分)。
如果esi包含某个计算的结果或参数值,这将是有用且高效的,但对于常量索引,更简单的方法是在编译时计算偏移量:

add eax, dword ptr [ebx+12]

还请注意,使用ecx来存储结果也是多余的。
下面是一个简化版本:

#include <stdio.h>

int main() {
    int a;
    int b[5] = { 1, 2, 3, 4, 5 };
    int *c = b;

    __asm {
        mov ebx, c
        mov eax, dword ptr [ebx]
        add eax, dword ptr [ebx+12]
        mov a, eax
    }

    printf("sum of first and fourth element is: %d\n", a);
    return 0;
}

但是请注意,目前还不清楚汇编代码是否会对ebxesi产生副作用而不产生后果...

相关问题