使用MMX内联汇编计算80元素无符号字符数组求和错误求助
问题分析与修正方案
你的代码存在多处关键错误,导致结果完全不符合预期,以下是具体问题和修正后的实现:
核心错误点
- ECX寄存器未初始化:循环依赖
dec ecx控制次数,但ECX没有设置初始值,循环次数完全随机,无法正确遍历80个元素。 - 错误使用MM寄存器作为地址指针:
movq mm1, [dataArray]是加载数组前8个字节到MM1,而非存储数组地址;add mm1, 8是对MM寄存器内的数据做加法,而非移动数组指针,根本无法遍历后续元素。 - 变量类型与指令不匹配:
sum是1字节的unsigned char,但movq sum, mm0会写入64位数据,直接覆盖相邻内存,导致sum值混乱。 - 未完成MMX寄存器内的字节累加:
paddb是字节级并行加法,最终MM0中是8个独立的部分和(每个字节为10),需要将这8个字节串行求和才能得到最终的80。
修正后的代码
#include <iostream> int main() { unsigned char dataArray[80]; for (int i = 0; i < 80; ++i) { dataArray[i] = 1; } unsigned int total_sum = 0; __asm { pxor mm0, mm0 // 初始化MM0为0,用于存储分组字节和 mov esi, dataArray // 用ESI寄存器存储数组起始地址 mov ecx, 10 // 循环次数:80个元素,每次处理8个,共10次 add_loop: movq mm1, [esi] // 加载当前8个字节到MM1 paddb mm0, mm1 // 字节级并行加法,MM0各字节累加对应MM1字节的值 add esi, 8 // 指针后移8字节,处理下一组元素 dec ecx // 循环次数减1 jnz add_loop // 未完成10次则继续循环 // 串行累加MM0中的8个字节(每个字节值为10) movq [total_sum], mm0 // 将MM0的64位数据临时存入total_sum的内存空间 mov eax, [total_sum] // 取低32位4个字节到EAX mov edx, [total_sum+4] // 取高32位4个字节到EDX add eax, edx // 累加高低32位,得到4个字节的和 mov edx, eax // 暂存结果到EDX shr eax, 16 // EAX右移16位,取出高16位 add dx, ax // 累加高低16位,得到2个字节的和 movzx eax, dx // 将16位结果扩展为32位 shr eax, 8 // EAX右移8位,取出高8位 add al, dl // 累加高低8位,得到最终总和80 mov total_sum, eax // 存储最终结果 emms // 退出MMX模式,恢复x87浮点单元状态 } std::cout << "Sum: " << total_sum << std::endl; return 0; }
关键修正说明
- 使用通用寄存器
ESI作为数组指针,ECX初始化循环次数为10,确保完整遍历所有80个元素。 - 用
unsigned int存储总和,既避免溢出,又能临时存放MM0的64位数据。 - 循环结束后通过多步串行累加,将MM0中8个独立的部分和合并为最终总和。
- 执行
emms指令退出MMX模式,这是MMX编程的必要规范,避免影响后续浮点操作。
内容的提问来源于stack exchange,提问作者Haider ali
相关产品推荐
相关产品推荐

