NASM下使用MMX指令对16元素字数组求和仅输出4个结果故障排查
问题分析与修复方案
问题原因
- 仅执行了一次MMX加法运算,未遍历完整数组:64位MMX寄存器单次可存储4个16位WORD类型的数组元素,当前代码仅完成了前4个元素的和计算,剩余12个NIZC数组位置为未初始化的内存垃圾值,因此只有前4个输出结果正确。
- 使用了错误的加法指令:
paddq是64位四字加法指令,不会按16位WORD拆分做逐元素计算,不符合需求中逐元素相加的要求。 - 输入环节存在内存越界写入:
read_int返回的32位整数存储在EAX寄存器中,直接将4字节的EAX写入仅预留2字节的WORD数组位置,会覆盖相邻的下一个数组元素,导致数组原始值本身存在错误。
修复方法
- 修正输入逻辑:将两个数组输入循环中写入数组的操作从
mov [NIZA+esi], eax、mov [NIZB+esi], eax改为mov [NIZA+esi], ax、mov [NIZB+esi], ax,仅写入16位的AX寄存器,避免越界覆盖。 - 新增MMX运算循环:16个元素单次处理4个,总共循环4次,每次处理后偏移量加8字节(对应4个WORD的长度)。
- 替换加法指令:将
paddq替换为paddw,实现逐16位元素相加。 - 新增
emms指令:MMX指令执行完成后执行emms清空浮点状态位,避免后续潜在的浮点运算出错。
修复后的核心运算代码
替换原代码中单次MMX运算的部分即可:
mov esi, 0 mov ecx, 4 ; 每次处理4个元素,16个元素共循环4次 calc_loop: movq mm0, qword [NIZA + esi] movq mm1, qword [NIZB + esi] paddw mm0, mm1 ; 按16位WORD逐元素相加 movq qword [NIZC + esi], mm0 add esi, 8 ; 每次偏移8字节,对应4个WORD的长度 loop calc_loop emms ; 清空MMX状态,符合编程规范
内容的提问来源于stack exchange,提问作者Tarik Pašić
相关产品推荐
相关产品推荐

