64 位系统 运行 可以包含一些内联汇编的 32 位软件吗?
Can a 64 bit system run a 32 bit software which contains some inline assembly?
所以,我的代码中有一部分没有汇编就无法完成,但我的软件需要能够 运行 在 64 位系统上,所以如果在 x86 机器上编译代码它会在 64 位机器上 运行 吗?如果不行怎么办?
我用汇编编写的函数需要在程序内存的 运行 时执行一些异或运算(一种防止调试的保护),具体来说,它会加密一些函数,然后在需要时解密。
__asm
{
push eax
push ecx
mov ecx, StartAddress
add ecx fSize
mov eax StartAddress
protect:
xor byte ptr ds:[eax], 0x25
inc eax
cmp eax, ecx
jl protect;
pop ecx
pop eax
}
您只能在 32 位环境中 运行 32 位进程。
大多数 64 位 OS 提供一些来自 32 位的支持。在 Win64 中,这称为 WoW64:(Win64 上的 Win32)。
如果 OS 不提供此支持,那么您就不走运了。例如Windows 2008 服务器 R2 WOW64 是可选的。
为什么你不能 运行 64 位模式下的 32 位代码
在 x64 中,单字节 inc/dec
指令已被重新用作 REX 前缀。
这意味着您的代码将在以下位置失败:
protect:
xor byte ptr ds:[eax], 0x25
inc eax <<-- will not work in X64
cmp eax, ecx
除此之外
mov ecx, StartAddress
....
mov eax StartAddress
不会工作,您需要将指针加载到 64 位寄存器中,否则如果加载到高地址,您的代码将失败。
尽管许多操作码在 x86 和 x64 之间是相同的。
64 位进程中的单个 运行 32 位代码将很快失败。
If not what can I do?
更改代码使其符合 64 位。
您需要将所有 pointers/addresses 更改为 64 位宽。
您需要将寻址内存的所有寄存器更改为 64 位。
__asm
{
push rax
push rcx
mov rcx, StartAddress
add rcx fSize
mov rax StartAddress
protect:
xor byte ptr [rax], 0x25 //ds is the default.
inc rax
cmp rax, rcx
jl protect;
pop rcx
pop rax
}
您不能在 64 位进程中 运行 32 位程序。
Win64 等人使用此技巧的唯一原因是 OS 根据需要执行特权模式更改回 32 位模式。
因为 Microsoft C++ 编译器不支持内联 64 位汇编,如果您想使用 64 位汇编,您将不得不使用 Embarcadero 的 G++ 的 C++builder。
So, I have a part in my code which can't be done without assembly
不,你不知道。您只是将一块内存与 0x25 进行异或运算。您应该用 C 语言编写并让编译器自动对其进行矢量化。
If compile the code on a x86 machine will it run on a 64 bit machine?
编译器输出也是汇编/机器代码。硬件 运行ning 您的代码不知道或不关心哪些指令是由编译器发出的,哪些是用内联 asm 手写的,或者作为单独的独立 asm 函数。
因此,从包含 inline-asm 的源构建的 32 位二进制文件仍然只是一个普通的 32 位二进制文件。
大多数主要 x86-64 操作系统的默认安装(包括大多数 Windows 版本,但不是全部(见评论))都支持 运行ning 32 位 x86 二进制文件,因为有是对 运行ning 32 位代码以本机速度的硬件支持。即使在系统调用上也基本上没有额外的开销。 In Windows, this is called WoW64(Windows 在 Windows64 上)。
你失去的只是 x86-64 代码可以 运行 更快的事实,因为它有更多的寄存器,所以编译器不必发出那么多的指令来溢出/重新加载数据 to/from 在内存中划痕 space。此外,两个主要的 x86-64 ABI 在寄存器中传递函数参数,而不是在堆栈中,再次降低了函数之间传递的延迟。 (请参阅 ABI 文档的 x86 标签 wiki,以及优化指南)。
具有大量指针密集型数据结构的程序在 x86-64 上实际上会变慢,因为更大的指针意味着更大的缓存占用空间。现在内存有点便宜,但是缓存还是很珍贵的。
所以,我的代码中有一部分没有汇编就无法完成,但我的软件需要能够 运行 在 64 位系统上,所以如果在 x86 机器上编译代码它会在 64 位机器上 运行 吗?如果不行怎么办?
我用汇编编写的函数需要在程序内存的 运行 时执行一些异或运算(一种防止调试的保护),具体来说,它会加密一些函数,然后在需要时解密。
__asm
{
push eax
push ecx
mov ecx, StartAddress
add ecx fSize
mov eax StartAddress
protect:
xor byte ptr ds:[eax], 0x25
inc eax
cmp eax, ecx
jl protect;
pop ecx
pop eax
}
您只能在 32 位环境中 运行 32 位进程。
大多数 64 位 OS 提供一些来自 32 位的支持。在 Win64 中,这称为 WoW64:(Win64 上的 Win32)。
如果 OS 不提供此支持,那么您就不走运了。例如Windows 2008 服务器 R2 WOW64 是可选的。
为什么你不能 运行 64 位模式下的 32 位代码
在 x64 中,单字节 inc/dec
指令已被重新用作 REX 前缀。
这意味着您的代码将在以下位置失败:
protect:
xor byte ptr ds:[eax], 0x25
inc eax <<-- will not work in X64
cmp eax, ecx
除此之外
mov ecx, StartAddress
....
mov eax StartAddress
不会工作,您需要将指针加载到 64 位寄存器中,否则如果加载到高地址,您的代码将失败。
尽管许多操作码在 x86 和 x64 之间是相同的。
64 位进程中的单个 运行 32 位代码将很快失败。
If not what can I do?
更改代码使其符合 64 位。
您需要将所有 pointers/addresses 更改为 64 位宽。
您需要将寻址内存的所有寄存器更改为 64 位。
__asm
{
push rax
push rcx
mov rcx, StartAddress
add rcx fSize
mov rax StartAddress
protect:
xor byte ptr [rax], 0x25 //ds is the default.
inc rax
cmp rax, rcx
jl protect;
pop rcx
pop rax
}
您不能在 64 位进程中 运行 32 位程序。
Win64 等人使用此技巧的唯一原因是 OS 根据需要执行特权模式更改回 32 位模式。
因为 Microsoft C++ 编译器不支持内联 64 位汇编,如果您想使用 64 位汇编,您将不得不使用 Embarcadero 的 G++ 的 C++builder。
So, I have a part in my code which can't be done without assembly
不,你不知道。您只是将一块内存与 0x25 进行异或运算。您应该用 C 语言编写并让编译器自动对其进行矢量化。
If compile the code on a x86 machine will it run on a 64 bit machine?
编译器输出也是汇编/机器代码。硬件 运行ning 您的代码不知道或不关心哪些指令是由编译器发出的,哪些是用内联 asm 手写的,或者作为单独的独立 asm 函数。
因此,从包含 inline-asm 的源构建的 32 位二进制文件仍然只是一个普通的 32 位二进制文件。
大多数主要 x86-64 操作系统的默认安装(包括大多数 Windows 版本,但不是全部(见评论))都支持 运行ning 32 位 x86 二进制文件,因为有是对 运行ning 32 位代码以本机速度的硬件支持。即使在系统调用上也基本上没有额外的开销。 In Windows, this is called WoW64(Windows 在 Windows64 上)。
你失去的只是 x86-64 代码可以 运行 更快的事实,因为它有更多的寄存器,所以编译器不必发出那么多的指令来溢出/重新加载数据 to/from 在内存中划痕 space。此外,两个主要的 x86-64 ABI 在寄存器中传递函数参数,而不是在堆栈中,再次降低了函数之间传递的延迟。 (请参阅 ABI 文档的 x86 标签 wiki,以及优化指南)。
具有大量指针密集型数据结构的程序在 x86-64 上实际上会变慢,因为更大的指针意味着更大的缓存占用空间。现在内存有点便宜,但是缓存还是很珍贵的。