程序集局部变量使崩溃

Assembly local variable makes crash

我用 nasm 语法编写了以下函数:

global _denseToDenseAddRelAVX_nocache_32_linux
_denseToDenseAddRelAVX_nocache_32_linux:

push    ebp
mov     ebp, esp

push    eax
push    ecx
push    edx
push    edi
push    esi

; edi: address1     [ebp + 8]
; esi: address2     [ebp + 12]
; edx: address3     [ebp + 16]
; ecx: count        [ebp + 20]
; xmm0: lambda      [ebp + 24]
; xmm2: relTolerance [ebp + 32]

mov     edi, [ebp+8]
mov     esi, [ebp+12]
mov     edx, [ebp+16]
mov     ecx, [ebp+20]
movlpd  xmm0, [ebp+24]
movlpd  xmm2, [ebp+32]

mov     eax, ecx
shr     ecx, 2
and     eax, 0x03

vzeroupper

vmovupd  ymm5, [abs_mask]

sub     esp, 16 ; make space for 2 doubles

movlpd  [ebp - 8], xmm2
movlpd  [ebp - 16], xmm0  ; <------ THIS LINE IS WRONG

add     esp, 16

pop    esi
pop    edi
pop    edx
pop    ecx
pop    eax

mov     esp, ebp
pop     ebp
ret

如果我删除行 movlpd [ebp - 16], xmm0,我的软件可以运行,但如果不运行,程序就会崩溃。如果我使用 8、9、10、11、12、13 和 14 而不是 16,我的软件将再次运行。当然,我使用最后 9 行进行调试,即我之前的函数 return。这段代码有什么问题? 我在32位保护模式环境下,我从c++调用这个函数。

[ebp - 8][ebp - 16] 写入数据在这里很糟糕,因为它会破坏保存的寄存器的值,而写入 [ebp - 16] 尤其糟糕,因为它会破坏 callee-save注册 edi.

未测试,请尝试避免像这样破坏保存的寄存器:

movlpd  [ebp - 28], xmm2
movlpd  [ebp - 36], xmm0

在你 make space for 2 doubles 的地方,你可能意味着存储相对于 esp 而不是 ebp,但无论如何你通过清理堆栈立即丢弃这两个值。您需要重新考虑如何 return 将值传递给调用者。

等等,刚注意到最后9行的部分。你可能想要的是:

movlpd  [esp], xmm2
movlpd  [esp+8], xmm0