Why were old games programmed in assembly when higher level languages existed?
I noticed that most if not all Nes / Atari, etc games were coded i开发者_C百科n assembly, however at that time, C, COBOL, and FORTRAN existed which I would think would make it easier to code right? So then why did they choose assembly over these available higher level languages?
Those games had 8-bit CPU chips and microscopic memories, like, 2kB. This answer would take up over half the RAM.
Compiled code was out of the question. Even on 8-bit CPU's with "large" memories, like "64K" (whee!) compiled code was difficult to use; it was not routinely seen until 16-bit microprocessors appeared.
Also, the only potentially useful language was C and it had not yet taken over the world. There were few if any C compilers for 8-bit micros at that time.
But C wouldn't have helped that much. Those games had horribly cheap hacks in them that pretty much required timing-specific instruction loops ... e.g., a sprite's Y-coordinate might depend on WHEN (in the video scan) its control register was written. (Shudder...)
Now there was a nice interpreted-bytecode language around that time or perhaps a little bit later: UCSD Pascal running on the UCSD P-System. Although I'm not a big Pascal fan, it was way ahead of everything else for those early processors. It wouldn't fit on a game or run fast enough for game play, though.
Performance, performance, performance. Games have always been all about getting the most out of the hardware. Even the best C, COBOL or FORTRAN compilers today can't compete with skillfully crafted assembly code.
As DigitalRoss has pointed out, there were also severe memory constraints, and assembly was the only tool that allowed for the fine grained control needed.
The same thing sort of applies today, although the old-days' assembler has been more or less replaced with C++. Even though programming languages such as Python exist (that are very easy to use), the low-level programming languages are still preferred for the most demanding applications.
"make it easier to code right"
Didn't matter.
High performance, minimal memory use was essential.
Easy to code was irrelevant.
Remember, early games had microscopic amounts of memory on very, very slow processors with no actual devices. Stuff was connected -- essentially -- directly to the CPU chip.
Compilers back then were not as good as the compilers we have now. Therefore many people felt, rightly or wrongly, that they could out optimize the compiler.
I would assume there were a much larger percentage of programmers that both knew assembler and wouldn't think twice about programming in assembler. And even into the IBM-PC and AT days folks that never really programmed anything but assembler were still around and could easily program circles around the C and Pascal programmers.
Pascal, and C were wonderful (for desktop computers) once they got a foothold and you could afford a compiler, you were happy to just be programming in some new language and had never heard of an optimizer, you just assumed the high level language turned into the machine code the same way with every compiler. You still easily fit your programs on a 5.25" floppy. And had plenty of that 640K to spare.
I think we need to bring back or have more 4K programming contests. Write a game for the GBA or NDS but the binary, data, code, everything, cannot be larger than 4K. Or perhaps re-invent the gameplay of asteroids, rocks, ship, bad guys, missles, don't worry about the video pixels because, first it wasn't, and second that was handled by a second processor (well hardware state machine), just generate the vector drawing commands. There are free 6502 C compilers out there now, and p-code based pascal compilers that it would be easy to run the output on the 6502, and see if you can get the frame rate up to real time at 1.5mhz or whatever it was running. And fit in the prom. I think the exercise will answer your question. OR...just make a runtime p-code interpreter and see if that fits. (standardpascal.org, look for the p5 compiler).
A handful of Kbytes is like a thousand lines of code or less. There just wasn't that much to the program, and assembler isn't difficult at all, certainly not on a 6502 or other similar systems. You didn't have caches and mmus and virtualization and multi core, at least not the headaches we have today. You had the freedom to chose whatever resister you wanted, each subroutine could use its own custom calling convention, you didn't throw away huge quantities of instructions juggling registers or stack or memory just so you could call functions in a standard way. You had but one interrupt and used it to time poll/manage the hardware (video updates, evenly timed polling of buttons and other user input, polling the quarter slot detector even while the game is being played).
Asteroids looks to be roughly 3000 lines of assembler. With the efficiency of the compilers now or then I would say you would need to write the whole game in about 500 lines of C code to beat that, pascal using p-code I will give you 100 lines of code, okay 200 (not p-code but optimized for the target I will give you more lines than C).
The Atari VCS (a.k.a 2600) didn't even have memory for a framebuffer for the video. The program had to generate the pixels just in time as well as perform all the game tasks. Sure, not a lot of pixels, but think about the programming task and the limited size and speed of the rom. For something like that you start getting into how many instructions per pixel, and we are talking a small number. High level compiled code is going to run in fits and spurts and not going to be smooth enough to guarantee the timing.
If you have the chance you should disassemble some of those old game roms, very educational, the instruction sequences were often very elegant. Optimized compiled high level code has cool tricks but it just isn't the same.
Supposedly better languages and compilers don't automatically make you better, faster, more efficient or reliable. Just like a fancy car doesn't make someone a better driver.
At the time they were developed, higher level languages were not available or did not perform well for the platforms on which they had to run.
Memory and speed have always been critical for games. My brother-in-law has a system that far outstrips the PC I run my virtual servers on, as well as desktop. He complains about the refresh rates on games. Assembly code can offer ability to optimize code not necessarily available from an old compiler. Modern optimizing compilers can do optimizations which make the resulting code faster than hand coded.
The old games relied heavily on CPU speed for timing. They are deadly to run on modern CPUs which run several times faster. One of the delay methods was to run a loop which incremented or decremented a counter a certain number of times. (These may get optimized out by a compiler.)
Although limited memory and limited speed were definitely an issue for Atari 2600 games, the main problem with a high-level language was a lack of control over timing. Just about every aspect of the system that involved timing had to be handled by the software including things like vertical blanking that typically you'd expect the hardware to do for you.
The more changes you made in position, color or data in a scan line the more critical the timing would become. In some cases you had to perform a write to a register a specific number of CPU cycles after the start of the line. If you were 1 CPU cycle early or 1 CPU cycle late the result would be incorrect.
Such timing precision just isn't practical using a high-level language.
精彩评论