How to make a 32-bit program from a 64-bit version?

5

3

Many software only supports 64-bit machine because the market for 32-bit is small now. However, for those who are stuck with 32-bit machines, this means newer versions cannot be installed, and this can lead to security issues. One example is Firefox/Waterfox.

In general, is there a way to make a 32-bit program from a 64-bit installation (.exe, .msi)?


See more: Why should browser's security be prioritized?

Ooker

Posted 2018-09-11T07:29:09.290

Reputation: 1 242

3If you could do it easily, so could software vendors and they would do it for you. – gronostaj – 2018-09-11T11:35:46.803

2It's also worth noting that if you're talking about an x86 system, it really is worth upgrading even aside from the security implications. An otherwise identical x86 system running 32-bit versus 64-bit will (almost) always perform better running 64-bit. – Austin Hemmelgarn – 2018-09-11T19:19:13.237

@AustinHemmelgarn I've thought that x86 is another way to say 32-bit? – Ooker – 2018-09-12T04:31:49.527

The correct names are x86 and x86-64. x86-64 is a superset of x86, so one could say that x86-64 processors are also x86. x86-64 CPU can be used like a x86 one, but it won't benefit from other x86-64 enhancements. – gronostaj – 2018-09-12T07:18:57.400

@gronostaj did you mean that x86-64 is a subset of x86? – Ooker – 2018-09-12T10:26:46.917

1No, x86-64 is a superset of x86. It contains all the features of x86 + more. x86 is a subset of x86-64. – gronostaj – 2018-09-12T11:03:23.750

1@Ooker It depends on the context. Realistically speaking though, when someone just says 'x86' without any specific qualifiers, they mean the architecture as a whole, not just the 32-bit version. – Austin Hemmelgarn – 2018-09-12T15:01:14.287

@gronostaj It's probably worth noting that your statement is only true of the hardware, and is not true of a direct comparison between long mode and legacy mode on 64-bit x86 CPU's (at minimum, some of the segment registers are unusable in long mode). – Austin Hemmelgarn – 2018-09-12T15:09:02.490

@gronostaj I understand what you mean. I was thinking about the definition of superset. A ⊂ B ⇔ all elements of A belong to B. So when you say that "x86-64 processors are also x86", it can only be understood that the former is a subset of the latter. – Ooker – 2018-09-12T15:15:05.760

Ooh, I get it now. You're thinking about processor sets defined by feature sets and I'm thinking about feature sets. – gronostaj – 2018-09-13T07:25:41.037

64-bit didn’t actually make systems faster. It made more real memory addressable. Having done performance work when 32 > 64 was happening it actually slowed things down. That said, I agree with the others...upgrade. So many benefits – Hogstrom – 2018-09-24T23:11:00.097

Answers

12

No, this is not possible. The reason why is quite broad, maybe even too broad for SuperUser, given that you would need to explain the fundamentals on how x86 and x64 were created, and how this influences programming in general.

But to explain briefly, it comes down to this:

In the past, we had 16-bit processors. Then intel made the first 32 bit processor, also known as x86. This is the 8086, 80286 (286 for short) etc... This was basically a modifcation to the 16 bit processors, with extra instruction sets added. With every new release of their processor series, Intel added more instruction sets to the processor family, which in the end caused the instructionset to contain many many instructions. Intel could not just remove old instruction sets because that would mean there was no backwards compatibility, and Intel wanted to keep supporting older processors.

As the processor is 32 bits, there is an upper limit, namely the highest 32-bit number. This means, that memory assignment only goes up to about 3,5GB.

Back in the days, computers were not so powerful, so if intel would aim for 64 bits from the start, it would mean that much more time was spent calculating the same numbers so performance would degrade simply because the numbers to calculate with are bigger.

Besides 32 bit processors worked quite well for a long time.

At some point, AMD entered the market and introduced the 64bit processor. AMD created their own instruction sets to allow working with 64 bits while keeping the intel instruction sets for 32 bits in tact to allow for backwards compatibility with 32 bits.

Given that they are in fact different instruction sets, a programmer who creates 32 bit programs will call different routines than when they create 64 bit programs.

Now that I explain why this is hard to do, lets continue to explain the problem from a programming perspective.

When you code a program, you write your code first. If your code is backwards compatible for 32 bits programs, you simply cannot use 64-bits numbers nor can you address more than 3,5gigs of memory at the same time. Basically, you cannot cross any limits that 32 bit programs face or your program will crash when done so.

As you now have code, only you can actually run your program. In order to make it so that other people can run your program, you have to compile the code into an executable. This means that the easy to read code is converted into instructions that the processor understands. During compile, you specify if your program is meant to run on x86 or x64, and the compiler will generate code using the instruction sets based on that processor architecture.

As you can see, you can't just modify an executable and make it work on a different executable. You first need to decompile the program to code, then recompile it using different instructions.

That said, given that a program that is compiled for x86 will natively work on x64, it is safe to assume that a programmer creates an x64 program because he is going to break limits of the x86 architecture. So even if you were to turn the x64 version into an x86 version, it is likely that the program will be unstable as you will cross the limitations of what a 32-bit program can do.

LPChip

Posted 2018-09-11T07:29:09.290

Reputation: 42 190

6Nice write-up. Technically not entirely correct, but as a simplified explanation it will do nicely. – Tonny – 2018-09-11T08:04:20.343

2Thanks. Yeah, it is hard to make it technically correct if you have to limit yourself. This is the best I could do to keep it suitable for SuperUser. – LPChip – 2018-09-11T08:11:40.570

9

Theoretically it can be done!

There are ways to translate from a neutral bytecode/internal representation to a specific architecture's binary like how modern compilers/JITters work. There are also emulators that run programs for another architecture on the current one. Bochs and qemu are two of the most famous ones. See:

Despite that I've yet to see anyone writing a converter like that for a single binary, because basically you'll also need to emulate every system and library calls, in which case it'd be better to run the whole emulator anyway. Qemu also has the ability to emulate only the user space, so it's actually possible to run a program along with its required libraries without a full-fledged OS. But as always, emulation is not meant for performance-sensitive things like web browsing or media playing

However if your x86 PC is 32-bit only, that means it's already more than 10 years old. Pretty much any Intel CPUs from Pentium 4 Prescott in 2004 onward (apart from some early Atom CPUs) and all AMD CPUs from Athlon 64 in 2003 onward are 64-bit capable. It's time to update.

If your PC is new enough to support x86_64 and VT-x then you can run a 64-bit virtual machine inside a 32-bit host, however it's not recommended and the performance will be even worse than running a 64-bit host with a 32-bit VM inside. A 64-bit OS doesn't need twice the memory compared to a 32-bit one like many people thought, so even with only 2GB of RAM, a 64-bit OS is generally still faster due to twice the number of registers and many other things. Between 1 and 2GB of RAM it's arguable but I'd go for 64-bit


That said, regarding security measures, 32-bit OSes nowadays are often late on security patches because developers all run a 64-bit system. For example the Meltdown and Spectre patches are pushed for 32-bit Linux more than half a year after 64-bit Linux has been patched. Meltdown patches are provided for 64-bit Windows 10 build 1507 and up but 32-bit users are only protected since build 1511. And even if they're patched, such ancient machines will usually face a lot more performance impact because they don't have the new instructions and features to offset the slowdown. Due to that reason MS doesn't enable the patch on some old PCs unless explicitly told by the user. And beside performance drop, a 32-bit patch will be more likely to be buggy because of a significantly fewer number of testers. See Linux's 32-Bit Kernel Has Been Buggy Since Being Mitigated For Meltdown:

Not only did it take months after Intel's Meltdown vulnerability was published (and x86_64 being mitigated) to see Linux KPTI support for x86 32-bit to mitigate Meltdown (from January's disclosure to mainline readiness in July), but it turns out it ended up exposing a 32-bit only bug that has lived in the kernel from summer 2018 until now [28 July 2019] with the Linux 5.3.

Sometimes they won't be patched at all because there's not enough user base, thus little incentive to spend the massive effort. The issue is also impossible to fix without hardware support if it's a hardware bug. For example recent side-channel attacks like Spectre or L1TF also need an updated microcode, so if the CPU and/or mainboard manufacturer don't release a firmware update, you're out of luck! Those bugs affect CPUs in the last two decades, but it's not possible to provide patches for very old systems. Windows 7 also dropped Pentium 3 support because it's too hard to patch without SSE2 support, or because too few people running it on those CPUs.

32-bit Windows is also more vulnerable because:

If you run a 64-bit OS in an emulator then it'll even be slower. And even if you accept the crawling speed and use an emulator then malwares on the host can still attack the virtual machine in such a vulnerable system. Again, time to update if you really care about security, or you'll have to live with less a secured system indefinitely

Further reading:

phuclv

Posted 2018-09-11T07:29:09.290

Reputation: 14 930

2"such ancient machines will face a lot more performance impact because they don't have the new instructions and features to offset the slowdown." - This isn't entirely true. There is absolutely no reason, I could not run a 32-bit operating system with an i7 8086K, and Windows 10. Just because the system is running a 32-bit operating system does not mean it's ancient. – Ramhound – 2018-09-11T11:08:41.607

on those systems it's better to run a 64-bit OS. In case a 32-bit OS is really needed, just run it in a VM. I've already stated that those applies to 32-bit only systems – phuclv – 2018-09-11T11:10:46.957

+1 for pointing out emulation (w/ binary translation) could do it. – Bob – 2018-09-11T11:24:58.653

See more: Why should browser's security be prioritized?

– Ooker – 2018-09-24T12:37:06.123

1@Ramhound is understating the issue somewhat. It's not just that you could choose to install a 32bit OS on a new system, at the bottom end of the PC market (eg atom with 2gb of ram) some systems have still sold with within the last 2 or 3 years with 32bit Windows even if they had a 64bit capable CPU. This is presumably partly because these systems have very small SSDs and win32 has a smaller footprint than win64, and partly because MS's cheapest tier of Windows licensing to major OEMs (this is not the same as the 'OEM' install you can buy as a consumer) was (is???) 32bit only. – Dan is Fiddling by Firelight – 2018-09-24T13:48:34.700

5

This is technically possible; the process is called binary translation.

You'll most often find this put into practice with emulators for disparate platforms (e.g. ARM on x86, x86 on ARM), or virtualisation where hardware acceleration is not available.

The biggest problem you'll face is that you cannot simply run most programs in a vacuum. They depend on the operating system's ABI, which typically varies between architectures. This means you end up needing to add a translation layer for all interactions with the OS (API calls, etc.), at which point you might as well emulate the entire OS ... which is described in phuclv's answer.

Bob

Posted 2018-09-11T07:29:09.290

Reputation: 51 526

1

Recompile the program to a 32-bit target

Your question was framed as having a 64-bit binary and wanting to run it as a 32-bit one, which is quite hard and you end up having to use an emulator or other complex issues.

However, if you have the original code in an high level language (as is the case for Firefox), you can probably compile it into 32-bit code.

Here, I respectfully disagree with the last paragraph of LPChip answer that a programmer creates an x64 program because he is going to break limits of the x86 architecture. They could be doing it because it is the default target, to match the native architecture, or simply to benefit from being able to use more memory if the user had enough RAM.

Some features like 64 bit counters made from 32 bit ones will be slightly slower than using a native register. If the program does use features specific to 64 bits (like inline 64 bit assembly) it won't work. The onus will be primarily on the compiler support on whatever high level language is being used (and the code on being well-written so it is quite portable to begin with).

If we focus on building Firefox / Waterfox, it is not a simple endeavor for the novice (nowadays browsers are like an OS of its own), less so with Firefox Quantum additionally requiring a rust compiler. Still, Linux distros still compile 32 bit versions of Firefox, showing that it can run under 32 bits.

Ángel

Posted 2018-09-11T07:29:09.290

Reputation: 960

While I generally like this answer, unfortunately, it's often not as simple as recompilation: while good practice suggests that developers should use platform-agnostic types (e.g. int32_t or int64_t instead of long or long long), that's unfortunately not always followed. If any assumptions about word size exist, compiling for a different architecture won't work. Similarly, if there are any x86_64-specific optimisations. Keep in mind that x86_64 provides many more general purpose registers than x86; it's not just pointer size that differs. – Bob – 2018-09-26T03:14:59.830