0

So, I have a part in my code which can't be done without assembly but my software needs to be able to run on 64 bit systems, so if If compile the code on a x86 machine will it run on a 64 bit machine? If not what can I do?

My function which is written in assembly needs to perform some XOR operations at runtime of the program's memory(kind of protection against debugging), to be specific it encrypts some functions then decrypts when needed.

__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
    }
Paralyz3d
  • 313
  • 2
  • 11
  • 1
    You realise that after `if I compile the code` there will be no assembly and it would be impossible to tell if there was any? At which point, http://stackoverflow.com/q/28307180/11683 – GSerg Sep 18 '16 at 16:01
  • That code can be done in C... – amchacon Sep 18 '16 at 16:03
  • Can you show me an example of that in C, I'd appreciate that? As far as I know in C you can't directly xor pointers. – Paralyz3d Sep 18 '16 at 16:07
  • 1
    Of course you can xor pointers. In C or C++. Either through the use of a few ugly casts, or in a union with an `integer` of the same size as the pointer. – Sam Varshavchik Sep 18 '16 at 16:10
  • You don't need to push/pop registers around an inline-asm statement. MSVC inline-asm syntax automatically implies that any reigsters used will be saved/restored by the compiler around your asm block. This is why [inputs and outputs require a store/reload round-trip](http://stackoverflow.com/a/35959859/224132). – Peter Cordes Sep 18 '16 at 16:23
  • @SamVarshavchik: **This code isn't even XORing pointers**, it's just dereferencing one as a memory destination. Compilers can and will do that, and this is a ridiculous way to generate slow byte-at-a-time code instead of letting the compiler auto-vectorize XOR-ing a block of memory with `0x25`. – Peter Cordes Sep 18 '16 at 16:25
  • 3
    Whether built/compiled on a 64-bit or 32-bit version of Windows, a program compiled to be a 32-bit application (even if it contains inine assembler) will run on 64-bit Windows through the transparent [WOW64 subsystem](https://en.wikipedia.org/wiki/WoW64). – Michael Petch Sep 18 '16 at 16:27
  • I am making an assumption from the inline assembler that the question is likely related to the MS Windows platform despite the fact that Windows wasn't mentioned or tagged. Previous questions asked by this user also suggest they may be on MS Windows. To @Paralyz3d was this question windows specific? My assumption may not have been accurate, thus the reason for me asking for clarification. – Michael Petch Sep 18 '16 at 16:34

2 Answers2

2

So, I have a part in my code which can't be done without assembly

No, you don't. You're just XORing a block of memory with 0x25. You should write that in C and let the compiler auto-vectorize it.

If compile the code on a x86 machine will it run on a 64 bit machine?

Compiler output is assembly / machine-code as well. The hardware running your code doesn't know or care which instructions were emitted by the compiler and which were hand-written with inline-asm, or as separate stand-alone asm functions.

So a 32-bit binary built from source that included inline-asm is still just a normal 32-bit binary.

Default installs of most major x86-64 OSes (including most Windows versions, but not all (see comments)) come with support for running 32-bit x86 binaries, since there is hardware support for running 32-bit code at native speed. There's basically no extra overhead even on system calls. In Windows, this is called WoW64 (Windows on Windows64).

All you lose out on is the fact that x86-64 code can run faster because it has more registers, so compilers don't have to emit as many instructions that just spill / reload data to/from scratch space in memory. Also, both major x86-64 ABIs pass function args in registers, instead of on the stack, again lowering latency of passing between functions. (See the tag wiki for ABI docs, and also optimization guides).

Programs with a lot of pointer-heavy data structures can actually slow down on x86-64, because larger pointers means a larger cache footprint. Memory is somewhat cheap these days, but cache is still precious.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • 1
    I upvoted but this isn't entirely true: `x86-64 OSes **all** come with support for running 32-bit x86 binaries` If you compile (for example) a 64-bit Linux kernel without 32-bit syscall support then most 32-bit applications will fail to work when run. It just happens to be that most Linux distros build a kernel with this feature by default, but anyone building a custom kernel can turn it off (it is a kernel build option) – Michael Petch Sep 18 '16 at 16:44
  • 1
    @MichaelPetch: xD, I already [mentioned that in a comment](http://stackoverflow.com/questions/39559636/can-a-64-bit-system-run-a-32-bit-software-which-contains-some-inline-assembly/39560110?noredirect=1#comment66430523_39559797), but misworded my answer. Thanks. – Peter Cordes Sep 18 '16 at 17:16
  • 3
    [WoW64 is optional in Windows Server 2008 R2 Server Core](https://blogs.msdn.microsoft.com/heaths/2009/11/06/wow64-is-optional-in-windows-server-2008-r2-server-core/): "*What does this mean for installation developers? Overall, 32-bit executables will not execute since the WoW64 subsystem is not installed*" – Remy Lebeau Sep 18 '16 at 17:20
1

You can only run 32 bit processes in a 32 bit environment.
Most 64-bit OS's provide some from of 32 bit support. In Win64 this is called WoW64: (Win32 on Win64).

If the OS does not provide this support then you're out of luck. In e.g. Windows 2008 server R2 WOW64 is optional.

Why can't you run 32 bit code in 64-bit mode
In x64 the single byte inc/dec instructions have been repurposed as REX prefixes.
That means your code will fail at:

    protect:
        xor byte ptr ds:[eax], 0x25
        inc eax                       <<-- will not work in X64
        cmp eax, ecx

Apart from that

    mov ecx, StartAddress   
    ....
    mov eax StartAddress

Will not work, you need to load pointers into 64 bit registers, or your code will fail if it's loaded at a high address.

Even though many of the opcodes are the same between x86 and x64.
A single run of 32-bit code in a 64-bit process will fail pretty quickly.

If not what can I do?

Change the code so that it conforms to 64-bit.
You need to change all pointers/addresses to be 64 bits wide.
You need to change all registers addressing memory to 64-bits.

__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
}

You cannot run a 32 bit program inside a 64-bit process.
The only reason Win64 et al manage this trick is that the OS performs a privileged mode change back to 32-bit mode as needed.

Because Microsoft C++ compilers are crippled and do not support inline 64-bit assembly you'll have to either use Embarcadero's C++builder of G++ if you want to use 64-bit assembly.

Johan
  • 74,508
  • 24
  • 191
  • 319
  • 1
    As was pointed out by @GSerg in the comments to me (now deleted) i also incorrectly assumed they were porting to 64-bit. It seems the real question is whether compiled 32-bit programs that used inline assembler would run on a Windows 64-bit platform AS a 32-bit program. – Michael Petch Sep 18 '16 at 16:14
  • As for your update. At least for MS C/C++ compilers targeting 64-bit programs, they haven't supported 64-bit inline assembler for quite a few years. – Michael Petch Sep 18 '16 at 16:15
  • 1
    I believe this answer has misguided the OP so well that they accepted it. They wanted that the `software needs to be able to run on 64 bit systems`. The answer is "Just compile it as is, it will work on x64 too". That is the case because the [processor itself supports it](http://stackoverflow.com/q/28307180/11683), not because Windows does a trick. The `You cannot run a 32 bit program inside a 64-bit process` is particularly misleading because it feels like a bold No, and yet it prohibits something the OP did not want in the first place. – GSerg Sep 18 '16 at 16:25
  • 2
    @GSerg: The OS does need to support 32-bit processes. e.g. you *can* build a version of the Linux kernel without support for 32-bit processes and the 32-bit syscall ABI compatibility layer. And you could avoid installing the 32-bit copies libraries. But if you do have all that in place, then yes there is hardware support for running 32-bit code at native speed, with basically no extra overhead even on system calls. – Peter Cordes Sep 18 '16 at 16:29
  • @GSerg, you cannot run 32-bit code in a 64-bit process. What don't you get about that? Windows runs 32-bit software in the WOW64 (Win32 on Win64) compatibility layer. Which is itself a 32-bit subsystem. – Johan Sep 18 '16 at 16:51
  • 1
    What I don't get about that is why you are mentioning this. No one wanted to run 32-bit code in a 64-bit process to begin with, yet you based your answer on saying it is impossible. The OP wants to run a 32-bit process on a 64-bit OS. – GSerg Sep 18 '16 at 16:58