【发布时间】:2016-04-05 02:55:07
【问题描述】:
所以我有一个带有 3 个参数 ASM_Method(void*, void*, int) 和 init_method(float, int*) 的汇编程序。感兴趣的是前者的 void 指针。
当我从 C++ 文件调用方法时,参数为:
float src[64];
float dest[64];
int radius[3];
init_method(1.5, radius);
ASM_Method(src, dest, 64);
这个调用过程的反汇编:
mov r8d,100h
lea rdx,[rbp+0A0h]
lea rcx,[rbp-60h]
call ASM_Method
初始化与否,程序运行良好。但是,当我这样做时:
float* src = new float[64];
float* dest = new float[64];
int radius[3];
init_method(1.5, radius);
ASM_Method(src, dest, 64);
调用时,RCX 设置的值不是正确的地址,但 RDX 是正确的。结果程序崩溃了。
这个调用过程的反汇编:
mov r8d,100h
mov rdx,rbx
mov rcx,rdi
call ASM_Method
除非我将 src 初始化为某些值,否则 RCX 在调用时会更改为无效地址(在本例中为 1)。
ASM_Method 的汇编代码:
mov rax, rdx
add rax, r8
shr r8, 4
inc r8
xor r9, r9
movdqu xmm1, [rax]
MainLoop:
movdqu xmm0, [rcx + r9]
movdqu [rdx + r9], xmm0
add r9, 16
dec r8
jnz MainLoop
movdqu [rax], xmm1
ret
init_method 的汇编代码:
mulss xmm0, xmm0
mov ecx, 4
cvtsi2ss xmm1, ecx
mulss xmm0, xmm1
shr ecx, 2
cvtsi2ss xmm2, ecx
addss xmm2, xmm0
sqrtss xmm2, xmm2
stmxcsr roundFlags
or roundFlags, 2000h
ldmxcsr roundFlags
cvtss2si ecx, xmm2
stmxcsr roundFlags
and roundFlags, 0DFFFh
ldmxcsr roundFlags
mov eax, ecx
dec eax
bt ecx, 0
cmovnc ecx, eax
mov eax, 3
cvtsi2ss xmm1, eax
mulss xmm0, xmm1
cvtsi2ss xmm3, ecx
movss xmm2, xmm3
movss xmm4, xmm3
mulss xmm2, xmm2
mulss xmm2, xmm1
mov eax, 12
cvtsi2ss xmm1, eax
mulss xmm3, xmm1
mov eax, -4
cvtsi2ss xmm1, eax
mulss xmm4, xmm1
addss xmm4, xmm1
mov eax, 9
cvtsi2ss xmm1, eax
subss xmm0, xmm2
addss xmm3, xmm1
subss xmm0, xmm3
divss xmm0, xmm4
cvtss2si eax, xmm0
mov esi, ecx
add esi, 2
mov edi, ecx
cmp eax, 0
cmovle edi, esi
shr edi, 1
mov dword ptr [edx], edi
mov edi, ecx
cmp eax, 1
cmovle edi, esi
shr edi, 1
mov dword ptr [edx + 4], edi
mov edi, ecx
cmp eax, 2
cmovle edi, esi
shr edi, 1
mov dword ptr [edx + 8], edi
ret
发生了什么事?
【问题讨论】:
-
我在
ASM_Method(void*, void*, int)中只看到3 个参数你应该显示ASM_Method的汇编代码 -
我在这里有点停顿,因为我看不出 RCX 会有 1 的原因。您能否向我们展示您的整个汇编程序文件和演示该问题的整个 C++ 程序?这必须比所显示的更多。我仍然对你说
ASM_Method(void*, void*, int)有 5 个参数这一事实感到困惑。你是说 3 吗? -
在 ASM_Method 中,您将
r8[has 64] 添加到rax[has&dest]。因此,rax 是&dest[16]。您将其加载到xmm1并在最后写回。所以,您正在保存/恢复dest[16..19]。但是,dest未初始化。那是你要的吗?否则,ASM_Method 似乎是使用 16 字节内存操作的memcpy的快速复制版本。 -
你还是没有按我说的做。我说过要发布您的完整 C++ 和汇编程序文件,并将其转换为Minimal Complete Verifiable Example。我什至在
init_method中提到这些问题的原因是因为我什至不知道它是如何到达您的ASM_method的,因为我希望init_method在尝试访问虚假内存地址之前很久就会出现段错误ASM_Method -
从案例 1/案例 2 asm 块:您的第三个参数是
64但 asm inst 是mov r8d,100h,这是256十进制 - 不是您指定的。这应该是mov r8d,40h在both 情况下。对于案例 2,我们需要从上面进行更多反汇编,因为我们没有设置rbx和rdi的代码。特别是,由于rcx在 ASM_Method 中出现错误,它是从rdi设置的,因此值 [及其历史] 特别重要
标签: assembly x86-64 masm calling-convention