4
\$\begingroup\$

Kip R. Irvine's book, Assembly Language for x86 Processors, sixth edition, begins by comparing the Assembly language against high-level languages. One of the pros for Assembly, was game development:

Game programmers are experts at writing code that takes full advantage of hardware features in a target system. They use assembly language as their tool of choice because it permits direct access to computer hardware, and code can be hand optimized for speed.

Whereas a high-level language:

Produces too much executable code, and may not run efficiently.

This caught my attention. While I do realize that Assembly can optimize your programs, perhaps even significantly, I wonder if, at this point, it is at all practical?

My skepticism comes from:

  • Assembly seems to be difficult to maintain.
  • High-level languages aren't so slow.
  • I'm pretty sure that we have a handful of cutting-edge games based solely on high-level languages.
  • A particular interest in game development is to make your product cross-platform. I can only think of this as a significant obstacle for anyone using Assembly.
  • How much is "too much" executable code? I'm not entirely sure how reliable can this measure be.

Even if he meant to use Assembly for specific portions of your game, it still seems (to me) somewhat unpractical.

I'm not particularly advanced in Assembly, so I'm not sure. Are these claims accurate?

\$\endgroup\$
  • 6
    \$\begingroup\$ Programmers haven't been granted direct access to hardware for years, you always go through an OS driver even (or especially) on consoles. These claims are out of date \$\endgroup\$ – Patrick Hughes Aug 24 '13 at 23:59
  • \$\begingroup\$ @PatrickHughes: I think the author meant this in opposition to some older high-level languages where a+b might be some involved interpreted call taking many hundreds of instruction vs just using the appropriate ADD instruction on the CPU. Of course you still have access to the raw hardware for plain computation tasks, just not most peripheral devices and the like (though those are sometimes opened up to direct register manipulation such as with the GPUs on certain current consoles). \$\endgroup\$ – Sean Middleditch Aug 25 '13 at 5:42
  • \$\begingroup\$ @SeanMiddleditch good points! I don't often think of someone posting this kind of question as being a dev on this or next gen console hardware so I filter my answers to what I think their reference point is in consumer space. I should be more careful with that and present both sides. \$\endgroup\$ – Patrick Hughes Aug 25 '13 at 6:20
  • \$\begingroup\$ @PatrickHughes: it's not a bad assumption to make. I tend to assume most questions here are from folks working on "simple" PC/mobile games, though I do usually try to be clear when I'm making that assumption Just In Case(tm). \$\endgroup\$ – Sean Middleditch Aug 25 '13 at 6:27
  • \$\begingroup\$ Simple answer is no, that statement only applied back when chips ran below a few megahertz and clock cycles were used for timing. \$\endgroup\$ – MickLH Oct 4 '13 at 18:19
13
\$\begingroup\$

99% of the time, the compiler will produce better assembly than you will.

That being said, its often very useful to be able to read assembly when working in performance critical environments for a couple of reason:

  1. Occasionally the compiler will do something that you're not expecting it to do, generating "bad" code, or otherwise non-optimal code.
  2. Debugging release builds on target hardware without any (or very few and untrustworthy) symbols.

These days, it's unusual to write pure assembly. You will have access to various low-level instructions by way of intrinsics. For example, a common intrinsic used on PS3/360 was __fsel. The intrinsic tells the compiler that you want to use a particular instruction, but it lets the compiler work out the best way to slot it into the trace, registers, etc.

So all in all, it's far more useful to be able to read, and understand assembly than it is to write it. Just as it is far more useful to understand how your CPU works, than it is to be able to build one ;)

\$\endgroup\$
  • 5
    \$\begingroup\$ +1 for "it's important to be able to read assembly". While it may not be necessary to write assembly, being able to read it is important when debugging release builds, 3rd party libraries and other stuff that while not very common, do appear from time to time \$\endgroup\$ – Panda Pajama Aug 25 '13 at 4:29
  • \$\begingroup\$ Not even just release builds. I had to track down a stack corruption bug in a debug pre-alpha build of my company's game last week, and being able to read the assembly (and know what the calling convention for the compiler is and how the stack is laid out!) was essential to solving that problem. Debuggers stop working when the information they rely on is corrupted! \$\endgroup\$ – Sean Middleditch Aug 25 '13 at 23:27
5
\$\begingroup\$

Portability

One thing to keep in mind is the issue of portability. It's common to need to develop games library or engine code that will run on a PC (x86), console (PPC for XBox360/PS3/WiiU and x86 for XBone/PS4), mobile (mostly ARM, rarely some x86 or MIPS), and so on. C and its ilk are pretty much as low-level as you can get and still be able to compile your code on a diverse set of CPU architectures.

Higher levels languages and frameworks can abstract even further. Developing your game in Android's Java for instance will let your game run on any Android device without even needing a recompile. Other languages like JavaScript or such will allow your game to run on any device.

Need

On another note, most games don't need to maximize hardware anymore. Look at the glut of Flash and JavaScript games. Look at tech like Unreal3 running in JavaScript via emscripten. They do need that portability, though. The big AAA games that are really stressing the hardware are all written in C++ (rarely C) and scripting languages for game logic and glue so it should be obvious they don't need assembly for speed. They all come out supporting 2-3 platforms at launch with another few usually coming out a few months later making it quite clear how important portability is.

Completely irrelevant of whether assembly is or can be more efficient than today's C/C++ compilers (and that's arguable), the end result is that the cons of using assembly vastly outweigh the potential benefits even when compared to very high level languages which are highly abstracted from the machine like JavaScript.

Cost

As a company picking a language for a new project you also have to weigh tools, productivity, and hiring. You can find a lot of people experienced in C++. There are very good tools available for it. The language is decent at allowing a developer to express algorithms directly without worrying about machine details and hence saving time. Other languages do even better in all these area.

If you go with assembly, you have a much smaller pool of developers to hire from. The tools amount to little more than a text editor. Every task is going to involve a lot more time and effort due to the need to explicitly walk the CPU through every non-reusable step of every algorithm.

If you are a company with X time to ship your product and Y dollars to get the job done, you really want a language with a competitive (and hence cheap and plentiful) market, time-saving tools, and good developer productivity.

Making your game faster doesn't make you money. Actually shipping the game within budget does make you money.

Knowledge vs Compilers

A developer who intimately understands the target architecture (the CPU instruction set, architecture, micro-architecture, system buses, peripherals, etc.) can probably write faster code in assembly. The vast majority of developers don't fall into that category, however. A modern C/C++ compiler often has a lot more knowledge about the architecture than most programmers and hence can often generate surprisingly good code (though of course they can still sometimes generate surprisingly bad code).

Keep in mind that modern compilers can employ a number of optimization passes that simply surpass the realm of viability for a human to employ, especially at the project sizes of today's games and on today's highly complex machines and OSes. Various forms of inter-procedural analysis (or whole program analysis) allow the compiler to look at the entire program in ways a human simple can't. They can reason about very complex sets of interactions. They can make decisions with more information than a human can typically deal with at once. This is basic to the trend of all information analysis (look at where data mining has come in recent years as further example). The compiler can often use very advanced and finely tuned heuristics

Observe how many things like the inline keyword in C++ is treated as a soft hint by most modern compilers. The simple truth is that most human beings, even very experienced ones, are simply terrible at determining when inlining (or other types of optimizations) are actually beneficial or hurtful. The compiler will often ignore the inline keyword in cases where its logic determines that inlining would be counter-productive. Especially with inter-procedural analysis, the compiler is able to figure out on its own when to inline functions and when not to, or even when to partially inline a function (a technique that vetted assembly programmers might already be aware of, but they're unlikely to know when to use for maximal benefit).

The point is that the core assertion of the book you're linking is simply dated. The compilers then were often dumber and the CPU architectures simpler for humans to deal with, but today we have significantly more capable (and complex) technology.

Case Studies

Others have noted that Rollercoaster Tycoon was possibly the last major game written in assembly, which came out in 1999. That's 14 years ago, a whole 2 years before GPUs and the programmable graphics pipeline (which must be coded in high-level languages if you're sticking with the latest DirectX or OpenGL APIs, I might note, as they've both deprecated and ceased maintaining their assembly syntaxes).

One might look at which games have been written primarily in assembly or which use assembly at all. I will note that not one of the three AAA engines I've dealt with professionally has had even an ounce of assembly; the closest they get is using compiler intrinsics.

I tried to look up a list of games known to be written in assembly language, but honestly can't find any. I can find a number of games documented to be written in very high level languages like JavaScript or ActionScript or Python and even articles from some of the most respected lead developers of cutting-edge engines like Tim Sweeney of Epic (Unreal Engine) looking at moving away from C++ to even higher-level languages (as far back as the early 2000s).

I'm not at all big on trying to pretend authoritative opinions are fact, but it's hard to disagree with the lead engineer of Unreal Engine and agree with an academic. Especially when it's hard to find any evidence that backs up said academic. If assembly were more practical, one would expect to see it praised by today's game developers a little bit more.

Conclusion

I wonder if, at this point, [assembly] is at all practical?

No.

\$\endgroup\$
  • \$\begingroup\$ "The point is that the core assertion of the book you're linking is simply dated. The compilers then were often dumber and the CPU architectures simpler for humans to deal with" - what makes things even more bizarre is that the book was published in 2010... it's actually talking about a reasonably modern tech level. \$\endgroup\$ – Maximus Minimus Aug 25 '13 at 10:35
  • \$\begingroup\$ @JimmyShelter: It's a 6th edition. A lot of times with books like that there are passages or core assumptions that just aren't updated or rewritten because it's too much work or just missed during editing. The 4th edition is very old in game tech terms and I can't easily find info about editions 1-3, but presumably they are quite ancient indeed. \$\endgroup\$ – Sean Middleditch Aug 25 '13 at 17:08
3
\$\begingroup\$

This statement is too broad and seriously out of date.

Using assembly a programmer can optimize the heck out of it. Highlevel languages abstract details away and are somewhat slower than assembler, but usually this doesn't matter.

"Premature optimization is the root of all evil."

While you surely can program a game in assembler, it isn't really practical. For 90% of the code it does not really matter, how fast it is. It's more important getting it done. Then do profiling and optimize the bits that are too slow. Maybe even rewrite some bits in optimized assembler, but not the whole game.

\$\endgroup\$
  • 3
    \$\begingroup\$ And when optimizing you will almost always get a huge boost from refactoring algorithms you are using relative to trying to instruction count and playing with individual instructions. \$\endgroup\$ – Patrick Hughes Aug 25 '13 at 0:16
2
\$\begingroup\$

Chris Sawyer wrote most of RCT in x86 assembly. That was probably one of the last games that used it extensively. Possible? Yes. Currently practical? No.

I am not going to bother restating other people's points about optimization.

\$\endgroup\$
0
\$\begingroup\$

This reads more like a statement by a die-hard assembly language hold-out than anything else; I'm not sure if it has any practical merit nowadays (actually I lie; I am sure; it has none) - maybe 15 years ago, not today, and not for a long time.

Let's look at some facts:

  • Hand-optimized assembly can be faster for sure, but you need to be really really good (and know exactly what you're doing) - i.e someone like Michael Abrash - in order to beat a modern halfway-decent optimizing compiler.
  • x86 is the past - Visual C++ no longer supports inline assembly in x64 programs, for example. I'm certain that nobody wants to limit their possibilities for porting to x64.
  • For optimization work that centers around the renderer, assembly doesn't matter a damn - this is all about handing over tasks to a faster processor.
  • Use of APIs and frameworks limits your ability to break into assembly; nobody in their right mind is going to write a game engine that doesn't use APIs or frameworks.
  • One area which is extremely performance-critical - game logic scripting - is exactly where you can't (and don't want to) use assembly.
  • Even in the final analysis, it's a far more productive use of time to optimize the algorithm rather than break into assembly. E.g. if a sort function was running slow, would your first instinct be to rewrite it in assembly, or would you instead just look for a faster sort algorithm? I know which one I'd do.

Looking at the author's home page, I see that he's very much rooted in academia and with little in the way of practical experience in basically anything (aside from being a founding programmer of a research company almost 30 years ago). That should be enough to establish his credentials.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.