程序集局部变量使崩溃
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
我用 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