AMD64 run on i586 or vice-versa? - c

I have a small C program that I wish to port from Linux to Windows. I can do this with the MinGW compiler, and I have noticed that it has two different prefixes, amd64 and i586. I am on an i686 computer and I was wondering if I compile my C program using and amd64 architecture, will it run on my i686 machine? And vice-versa?
UPDATE:
Is there a compiler that compile C code to run on ANY architecture?

If you compile your code for i586 (actually what is commonly called x86) it should work fine on AMD64 (x86-64) processors, since x86-64 processors can execute "legacy" 32 bit code, as long as the OS supports this - and mainstream OSes usually do; Windows support for 32 bit applications in particular is really good, since most applications installed on the average Windows system are still 32 bit.
The contrary instead does not hold true, since the x86-64 instruction set is (loosely speaking) an expansion of the x86 architecture, so any non-64 bit x86 processor wouldn't know how to interpret the new machine code (and even if it knew it, it wouldn't have the resources to run it).
As for the edit, you can't generate machine code that runs natively everywhere; the usual solution in such cases is to use pseudo-compiled languages that output an intermediate-level machine code that needs an architecture-specific VM installed to be run (the classic example here is Java and .NET). If instead you use a language compiled to "native code", you have to generate an executable for each target platform.

Related

Compiling C code in Julia benchmark tutorial

After running the code in the first cell of this lecture, I am trying to call the function c_sum. However, I keep receiving the error:
error compiling c_sum: could not load library "/tmp/juliaOT2a9V"
/tmp/juliaOT2a9V.so: wrong ELF class: ELFCLASS64
I have tried modifying the code with the gcc flag -m64, but this hasn't helped. I'm new to coding, so I'm fairly confused as to what precisely the problem is, and how to fix it. Any help would be greatly appreciated!
Based on the error, it seems like the issue may be that you're trying to load a 64-bit shared object (.so) file into a 32-bit julia binary. What does your Julia versioninfo show? Here's mine:
julia> versioninfo()
Julia Version 1.6.0-DEV.420
Commit 0d5efa8846 (2020-07-10 14:27 UTC)
Platform Info:
OS: macOS (x86_64-apple-darwin19.5.0)
CPU: Intel(R) Core(TM) i7-8559U CPU # 2.70GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-9.0.1 (ORCJIT, skylake)
Environment:
JULIA_EDITOR = subl
JULIA_SHELL = /bin/bash
JULIA_INPUT_COLOR = bold
JULIA_ANSWER_COLOR = light_magenta
JULIA_PKG_DEVDIR = /Users/stefan/dev
If yours indicates that you're running a 32-bit julia, then you can either try installing a 64-bit julia or try compiling the C code to a 32-bit ELF shared object file using the -m32 flag rather than the -m64 flag. You can also use file to externally detect the format of these files, for example here's what I get on my macOS system:
julia> run(`file $(Sys.which("julia"))`);
/Users/stefan/dev/julia/usr/bin/julia: Mach-O 64-bit executable x86_64
julia> run(`file $(Clib * "." * Libdl.dlext)`);
/var/folders/4g/b8p546px3nd550b3k288mhp80000gp/T/jl_ZeTKsr.dylib: Mach-O 64-bit dynamically linked shared library x86_64
Since both my julia executable and the shared library file are Mach-O 64-bit, they're compatible and the example works. On your system julia may be 32-bit while gcc is generating 64-bit binaries by default because you're on a 64-bit system. This will probably be a problem in general, so even if passing the -m32 flag to gcc solves the immediate problem and allows you to make the example work, I would recommend using a 64-bit Julia binary instead. As a bonus, that will allow you to load larger data sets than a 32-bit Julia can, since the 64-bit binary can address all of your computer's (virtual) memory instead of just 4GB of it.
Historical note: How/why does your 64-bit Linux machine run both 32-bit ELF and 64-bit ELF files on a single system? In 2001, Intel introduced the Itanium IA-64 architecture, which was a pure 64-bit architecture meant for high-end servers. A year later AMD introduced the competing x86_64 architecture, which supported two process modes: 64-bit mode and 32-bit (legacy) mode. So you could have different processes on the same system running with different word sizes. IA-64 never really took off whereas x86_64 was wildly successful and eventually Intel started making x86_64 chips as well, which is probably what your machine is running, although it could also be an AMD chip. So now there are two different kinds of ELF binaries and that can both work on most PCs, but the granularity is process-level: you cannot load a 64-bit shared object into a 32-bit process or vice versa. Although your system can run 32-bit processes, since the system is primarily 64-bit, most of the programs and libraries are going to be 64-bit, which is why I've recommended that you switch to using a 64-bit Julia build.
More information about ELF-type mismatches here:
gcc error: wrong ELF class: ELFCLASS64.

The CPU dependency of C - is it really only CPU dependency?

C is a compiled language that compiles to native CPU instructions, as you know.
But if C compiles differently to each CPU, then why don't basic Windows programs work on a Mac, for example (considering they both have a processor from the Intel 386 family)?
A good example of that is the printf function in C, that would compile differently on
Windows and on a Mac OS X, even if they both sit on the same kind of processor (Intel 386).
I'm not actually sure that it really compiles differently under each OS, but the fact that a simple Windows application that outputs "Hello World!" to the Console Window won't open on a Mac, kind of make it seem like it compiles slightly differently.
I know for sure that GUI compiles differently because it calls system functions to draw on the screen, but why printf compiles differently on each OS? I thought it was CPU dependent, not OS dependent, and from what I know a Windows PC and a Mac both having an Intel 386 CPU means they both have the same instruction set.
So can you guys explain this, please?
The C standard specifies the language and a very API and expected behaviour of a very minimal run-time library to support it.
It specifically does not specify the specifics of object-file format produced by the compiler - necessarily so - as we'd expect object files produced by C compiler to link with other libraries provided by the platform, and for the system linker to link them.
Taking your example of two systems with CPUs running on hardware with the same architecture (Windows and MacOSX) - the way dynamic linking on these platforms works under the hood is quite different, as are the object files produced by the compiler. Even with systems using the same CPU, there may also be ABI differences as well.

Compile C program to run everywhere?

I understand that when the C compiler compiles code, it compiles it into machine code that is specific to the processor that it was compiled on. Is it possible to compile my C program on an Intel machine for example, and have it run on an AMD one without needing to recompile it on a machine with an AMD processor?
In fact both common Intel and AMD processors are based on X86 architecture. Although C program cannot be compiled once and run "everywhere", but Intel and AMD processors are really the same place in this sense.
For example you don't really worry about a single executable (say a game installer) wont be able to run on your windows machine regardless of it's Intel or AMD inside.
It's other architectures (different instruction set) such as Mac/ARM/68k etc you need to worry about recompiling

I am developing a 64 bit application. Is it possible to run the 64 bit application on a 32 bit OS?

I am developing a 64 bit application. Is it possible to run the 64 bit application on a 32 bit OS?
Please note that the question is generic and not specific to Windows OS. Infact the application in itself is portable across OS.
(We'll assuming your talking about AMD64 (== EM64T == x86_64) and x86 for 64-bit and 32-bit respectively)
You can run AMD64 code on x86 processors only by emulation (e.g. qemu), or some kinds of virtualisation (I believe VMWare might support 64bit guest OS on 32bit host OS on 64
bit capable CPU). However this means running a 64-bit OS as a guest on emulation or virtualisation I believe.
As you're developing the application, it shouldn't be too hard to develop both 32-bit and 64-bit builds of your code.
For Mac you can ship a single binary that has both types of code in it, or Mac OSX can run your 64-bit binary on a 32-bit kernel (only on a x86_64 capable processor though). For Windows and Linux, you'll either have to ship separate installers, or ship some smart installer, that selects the correct binaries at install time. For Linux there is a project for add the ability to run AMD64 code on x86 kernel on AMD64 processor - http://linuxpae64.sourceforge.net/ - but it doesn't look like it's got very far into the mainline kernel.
Is there a particular reason you only want to produce 64-bit binaries?
If it's to access extra memory, then the 32-bit OS wouldn't be able to give you extra memory anyway.
If it's to avoid have to test 2 different versions, then just produce the 32-bit version, it'll work on Windows AMD64, and most Linux AMD64 distributions without problems.
On windows, only using a virtual machine.
On OS X, 64Bit apps run natively (thanks Stephen)
The other way around is fine, bit I dont think you can run a 64bit app on a 32bit OS, you may be able to using a virtual machine or some kind of virtualisation.
There's an easier solution than trying to run a 64-bit program on a 32-bit OS (including executing through an emulated or virtual 64-bit platform on top of the 32-bit OS): recompile it for the 32-bit OS.
When you said it's portable across different OSes, did you also mean non-64-bit OSes? I could not call something portable without qualifying "only 64-bit" if that was the case, and I think many (maybe even most?) programmers also expect that qualification, at least currently.
it is possible using qemu in soft emulation mode
No.
See Microsoft FAQ:
The terms 32-bit and 64-bit refer to
the way a computer's processor (also
called a CPU), handles information.
The 64-bit version of Windows handles
large amounts of random access memory
(RAM) more effectively than a 32-bit
system. For more details, go to A
description of the differences between
32-bit versions of Windows Vista and
64-bit versions of Windows Vista
online.
Understand the difference between 32-bit and 64-bit and you will see why it's not possible.
See this (assuming you're running Windows):
If the program is specifically designed for the 64-bit version of Windows, it won't work on the 32-bit version of Windows. (However, most programs designed for the 32-bit version of Windows will work on the 64-bit version of Windows.)
Device drivers designed for the 64-bit version of Windows won't work on computers running a 32-bit version of Windows. To learn how to check for drivers, see Update a driver for hardware that isn't working properly or go to the device manufacturer's website.
On Windows, no. On OS X, yes. I don't know what the state of affairs is on Linux.
In fact, Snow Leopard boots into a 32-bit kernel, but compiles applications 64-bit by default, so this is quite common on OS X.
A 64 bit application does not run on a 32 bit processor period
A 64 bit application uses a 64 bit wide register. It just plain won't fit.

Do Intel and AMD processor have the same assembler?

The C language was used to write UNIX to achieve portability -- the same C language program compiled using different compilers produces different machine instructions. How come Windows OS is able to run on both Intel and AMD processors?
AMD and Intel processors(*) have a large set of instructions in common, so it is possible for a compiler or assembler to write binary code which runs "the same" on both.
However, different processor families even from one manufacturer have their own sets of instructions, usually referred to as "extensions" or whatever. Ignoring the x87 co-processor, the first time I remember this being a marketing point was when everything suddenly went "with MMX(TM) technology". Binary code expected to run on any processor either needs to avoid extensions, or to detect the CPU type before using them.
Intel's Itanium 64-bit architecture was completely different from AMD's x86-64 architecture, so for a while their 64bit offerings were non-compatible (and Itanium was nothing like x86, whereas x86-64 extended the instruction set by adding 64bit instructions). Intel blinked first and adopted x86-64, although there are still a few differences: http://en.wikipedia.org/wiki/X86-64#Differences_between_AMD64_and_Intel_64
Windows probably uses the common x86 or x86-64 instruction set for almost all code. I wouldn't be surprised if various drivers and codecs are shipped in multiple versions, and the correct one selected once the CPU has been interrogated.
(*) Actually, Intel make or have made various kinds of processors, including ARM (Intel's ARM processors were called XScale, but I think they've sold that business). And AMD make other processors too. But we know which Intel/AMD processors you mean :-)
AMD are Intel compatible, otherwise they would never have gained a foothold in the market place.
They are effectively clone compatible.
As you suspect, the main stream Intel and AMD processors have the same instruction set.
Windows does not run on ARM or PowerPC chips, for example, because it is somewhat dependant on the underlying instruction set.
However, most of Windows is written in C++ (as far as I know), which should be portable to other architectures. Windows NT even ran on PowerPC and other architectures.
Intel's 80x86 CPUs and AMD's 80x86 are "mostly the same sort of", but some things are completely different (e.g. virtual machine extensions - SVM vs. VT-x) and some things (extensions) may or may not be supported. However, some things are different on different CPUs from the same manufacturer too (e.g. some Intel chips support AVX2 and some don't).
There are multiple ways to deal with the differences:
only use the common subset so the same code runs on all 80x86 CPUs (e.g. treat it like an 8086 chip).
use a subset of features that is common to a range of CPUs so the same code runs on all 80x86 CPUs in that range. This is very common (e.g. "this software requires an 80x86 CPU (and OS) that supports 64-bit extensions").
use install-time tests. For example, there might be 4 different copies of software (compiled for 4 different ranges of CPUs) where the installer decides which copy makes sense for the computer the software is being installed on.
use run-time tests. For example, code can use the CPUID instruction to do if( AVX2_is_supported() ) { set_function_pointers_so_AVX2_is_used(); } else {set_function_pointers_so_AVX2_is_not_used(); }. Note: Some compilers (Intel's ICC) can automatically generate code that does run-time tests.
These aren't mutually exclusive options. For example, the installer might decide to install a 64-bit version (and not a 32-bit version), and then the 64-bit version might check which features are supported at run-time and have different code to use different features.
Also note that different parts of an OS can be treated separately. For example, an OS could have 6 different boot loaders, 4 different "HALs", 4 different kernels, and 3 different "kernel modules" to support virtualisation; where some of these things might do run-time tests and some might not.
Do Intel and AMD processor have the same assembler?
Almost all assemblers for 80x86 support almost all extensions (from all CPU manufacturers - e.g. Intel, AMD, VIA, Cyrix, SiS, ...). In general; it's up to the programmer (or compiler) to make sure they only use things that they know exist. Some assemblers provide features to make this easier (e.g. NASM provides a CPU ... directive so that the programmer can tell the assembler to generate errors if it sees instructions that aren't supported on the specified CPU).
AMD and Intel use the same instruction set.
When you install windows on an AMD processor or an Intel processor, it doesn't "compile" code on the machine.
I remember many people being confused on this subject back during college. They believe that a "setup" means that it is compiling code on your machine. It isn't. Most if not all Windows application outside of the free realms, are given to you by binary.
As for portability, that isn't neccessarily 100% true. While C is highly portable, in many cases writing for a specific OS or system will result in the code only being able to compile/executed on that box. For example, certain Unix machines handle files and directories differently so it might not be 100% portable.
Do Intel and AMD processor have the same assembler?
An assembler assembles a program to be run on a processor, so your question is flawed. Processors DO NOT use assemblers.
If you mean can Intel and AMD processor run the same assembler? Then the answer is YES!!!
All an assemblers are, is a program that assembles other programs from structured text files. Visual Basic is an example of an assembler.

Resources