我是汇编语言编程的新手,面对的问题对于有经验的汇编语言用户来说可能是显而易见的。我有一个100字节的缓冲区,我需要找到n = 1到5的每个第n个字节的总和,并将结果存储在5个整数的数组中。我需要在我的c ++代码中使用内联汇编来执行此操作。我写了以下代码:
void main()
{
char *buffer = new char[100];
int *result = new int[5]();
for (int i = 0; i < 100; i++)
buffer[i] = i;
char *start = buffer;
for (int k = 0; k < 20; k++)
{
for (int j = 0; j < 5; j++)
{
__asm
{
mov eax, start[j]
mov ebx, result[j]
add eax, ebx
mov result[j], eax
}
}
start += 5;
}
}
所以最后,result [0]应该有缓冲区[0],缓冲区[5],缓冲区[10] ....之和,结果[1]将有缓冲区[1],缓冲区[ 6],缓冲[11] ....等等。 我在第一个汇编指令本身遇到了Access Violation错误(mov eax,start [j])。任何人都可以帮我找出我所犯的错误吗?如果有人可以帮我用汇编语言编写整个循环和求和部分,那就太棒了
答案 0 :(得分:1)
显然我不知道你的实际意图,但我质疑“我想使用这个概念的真实场景可能带来一些好处。”
说人类不能再为i386编写高效的汇编程序可能不是100%准确,但这几乎是正确的。如果您熟悉流水线操作和乱序执行,那么您已经理解为什么会这样。如果你不熟悉这些,你已经说过你不知道如何编写高效的汇编程序。
这并不是说您不应该查看程序热点的汇编程序。但是你应该编写最有效的c代码并对其进行基准测试,然后再尝试查看是否可以在asm中编写更好的东西。如果你不能,不要感到惊讶。
那就是说,你可以尝试这样的基准测试。我的猜测是它会更好,但这只是猜测。
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 100
#define MAXTOT 5
typedef unsigned char BYTE;
int main()
{
BYTE *buffer = (BYTE *)malloc(MAXSIZE);
const BYTE *start = buffer;
unsigned int t0, t1, t2, t3, t4;
for (int i = 0; i < MAXSIZE; i++)
buffer[i] = i;
t0 = 0;
t1 = 0;
t2 = 0;
t3 = 0;
t4 = 0;
for (int j=0; j < (MAXSIZE / MAXTOT); j++)
{
t0 += start[0];
t1 += start[1];
t2 += start[2];
t3 += start[3];
t4 += start[4];
start += MAXTOT;
}
printf("%u %u %u %u %u\n", t0, t1, t2, t3, t4);
free(buffer);
return 0;
}
循环在asm中看起来像这样(使用gcc -O2):
L3:
movzbl (%edx), %edi
addl $5, %edx
addl %edi, 44(%esp)
movzbl -4(%edx), %edi
addl %edi, %ebx
movzbl -3(%edx), %edi
addl %edi, %eax
movzbl -2(%edx), %edi
addl %edi, %ecx
movzbl -1(%edx), %edi
addl %edi, %esi
cmpl 40(%esp), %edx
jne L3
这样可以在计算期间尽可能多地保留寄存器中的“结果”(而不是像现有代码那样不断地将它们全部读取/写入内存)。更少的循环也意味着更少的cmp指令,这只通过缓冲区而不是5次。编译x64(现在没有asm更容易)提供更好的代码,因为有更多的寄存器可供使用。
如果MAXTOT变大,显然会崩溃。但我只能对我能看到的代码发表评论,而5就是你所使用的代码。
FWIW。