2
votes

I recently read that the game rollercoaster tycoon 2 was written in assembly language.

I am interested in learning the basics of assembly language mainly out of curiosity however one thing that I can't understand is how it worked on a range of CPU's.

Am I right in my understanding that assembly language is specific to an instruction set? So how did this game run on both intel and AMD CPU's if it was written in assembly language?

4
Either the instruction between the two CPU sets sufficiently overlap, the developers used an emulator one of them, or it didn't happen.nicomp
I've just realised it was in an emulator. Thanks. And do intel and AMD share the same instruction set?Sam
@Sam yes (there have been tiny differences over the years, but if you need to ask, the answer's yes).Leushenko
the instruction sets have a large overlap.old_timer

4 Answers

2
votes

Rollercoaster Tycoon 2 only runs on PCs running Windows. PC in this sense means IBM PC compatible, that is backward compatible with the original IBM PC which used an Intel 8088 CPU. The 8088 was cheaper version of the 8086, and so this means all PCs use a version of the 8086 instruction set. Over the years Intel released CPUs that expanded this instruction set. Most notably the Intel 80386 added 32-bit support.

Being a 32-bit Windows game with a Pentium II CPU given as the minimum requirement, RCT2 would be written entirely or almost entirely using instructions supported by the 80386. The weren't that many instructions added by the later 80486, Pentium and Pentium II processors. A notable exception would be the MMX instructions, but these were hard to use and probably not useful for this sort of game. Also the original Railroad Tycoon supported Pentium CPUs, but only later "MMX" versions of the Pentium supported these instructions.

So the game works on Windows PCs that support a modern enough version of 8086 instruction set. This includes both Intel PCs and AMD PCs (and Via PCs), since all PCs have CPUs that use the 8086 instruction set. Any PC with an AMD CPU fast enough to run the game an acceptable speed would support a modern enough version of the 8086 instruction set. That would include all AMD PCs sold in the last 15 years.

Note that fact that a game was written in assembly language or not doesn't really make any difference to the end user. A game written completely in C++ will be compiled into machine code before being delivered to customers. Similarly a game a written entirely in assembly is assembled in to machine code. A Windows game, whether written in C++ or assembly, will only work on a Windows PC that supports a modern enough version of the 8086 instruction set.

The fact that RCT2 was written in assembly only makes a significant difference to the developers and publishers of the game. A game written in C++ can be ported relatively easily to other platforms. It's usually not as simple as recompiling the game to produce machine code for the other platform, but usually only a relatively small part of the C++ code needs to be changed. Porting RCT2 to the PlayStation 2 or PowerPC-based Apple Macs would require completely rewriting every line of source code.

There's project called OpenRTC2 project which has effectively done just that. They've reversed engineered the game and rewritten it from scratch in C. This has allowed them produce versions of their game that run on platforms other than Windows PCs.

1
votes

To my understanding, it is impossible to natively execute machine code generated for one processor type on an incompatible processor type. However, a virtual machine, also called emulator, can be used to achieve a non-native execution of machine code which actually is tageted at a different processor type.

1
votes

There's a subtlety in how you're defining assembly language. A language that undergoes significant transformations and doesn't map exactly to the resulting machine instructions obviously isn't an assembly language, but that doesn't necessarily make it specific to an instruction set, either.

In theory, you could have one assembly language that produces machine code for multiple architectures by restricting it to a common subset of very widely-supported operations, such as add, multiply, divide, etc. As long as the architectures are similar enough in how they implement this subset of instructions, and you can write a working program with this subset, the same assembly listing can reasonably be said to run on all of them; it might need to be translated to different opcodes, but the structure of the binary will be the same in all cases. This is especially the case if you're willing to admit e.g. a 1:N rather than 1:1 correspondence between assembly operations and machine instructions (where N is variable between architectures, but constant on one), to allow e.g. three-address-style assembly, which would be 1:1 on ARM, to "assemble" for x86, by having all assembly instructions expand to two x86 ops instead of one.

One possible example of such an assembler is the PicoLisp assembly language, used to write the 64-bit version of the interpreter. It claims to be mostly portable between ARM, PPC, x86, and C (with some platform-specific code to tie the chunks together).

1
votes

All x86 microarchitectures (Intel's 386/486/Pentium/P6-family(PPro to Nehalem)/P4/Sandybridge-family/Atom/Silvermont, AMD's K6/K7/K8/K10/Bulldozer-family/Bobcat/Jaguar/etc, Via's Nano, Transmeta's Crusoe, etc. etc.) are implementations of the x86 ISA (Instruction Set Architecture).

That's what makes them x86 microarchitectures. They have different internals, and you'd optimize for each one slightly or a lot differently, but the same instruction sequence will have the same effect on their architectural state. I.e. they run the same code, and you can think about them in terms of the x86 machine model they implement, rather than thinking about their internals, which can be totally different, most spectacularly in the case of Transmeta's on-the-fly software-base binary translation to VLIW machine code. The internals of out-of-order execution CPUs from Intel and AMD are also very different from the x86 architectural state, but they decode instruction using hardware decoders. Intel SnB-family CPUs do cache the results of decoding x86 machine code to internal uops, though.

Some x86 implementations will support instruction-set extensions that others don't, but you can write code that uses the CPUID instruction to decide at run-time which versions of functions to use, based on the capabilities of the CPU your code is running on: e.g. the baseline version, the SSE2 version, the SSSE3 version, or the AVX version.)

When making x86 binaries, you are targeting the x86 ISA, which is standardized by Intel. See the links in the wiki. The pdfs are freely available.