3 ms·
>Assembly (specially on the 6502) is conceptually very simple and, while it may not be trivial to translate higher-level concepts to its simplicity, as long as
by simias 9y ago
>Assembly (specially on the 6502) is conceptually very simple and, while it may not be trivial to translate higher-level concepts to its simplicity, as long as what you want can be readily expressed in it, it's trivially easy.
That's precisely why I would qualify ASM as "tricky" and "tedious". You're bogged down in the tiny details that nowadays a compiler would probably solve as well (or even better) than you do. If you want to express "I want to make a function that adds two integers" then yeah it's trivial. If instead it's "I want to iterate through the leaves of a binary tree and compute its standard deviation" then have fun; good luck.
"This is a multiplication by 5, it's pretty expensive, probably better off shifting by two and adding once. Oh but then I need an intermediary register, do I have one available?"
"I guess I could inline this bit of assembly here instead of making a function call. Oh but wait now I need to re-do my register allocation to match."
"I need to reserve a bit more stack space to bank this register, let's modify my function's prelude and prologue to match."
Ain't got no time for that.
I think writing assembly is a skill any coder should have, especially if you usually deal with close-to-the-metal languages like C, C++ or Rust for instance. I think having a good grasp of assembly will make you a better coder, if only because it'll let you read the assembly output of your compiler to figure out what gets optimized and how (and also maybe what you could change to speed things up). There are also a few situations where writing assembly is the right solution.
That being said you'd have to pay me a lot to write a full application in assembly, regardless of how many layers of macros and pre-processing steps I'm allowed to use (unless gcc is allowable as a pre-processing step...)
- jacquesm 9y agoIt's the difference between being a plumber and being someone who makes custom jewelry. Both are artisans of a kind, the one is doing production and trying to 'get the job done' the other is making one-offs that will have a vastly inefficient time:product ratio where a lot of the value created will be in the eye of the beholder. Both are valid paths.
- simias 9y agoIt's more like someone making custom jewelry using modern tools vs. somebody making custom jewelry only using methods available in ancient Rome. You might not see any obvious difference looking a the result but once you know how they're made one is definitely more impressive than the other. I'm also sure that one is more "tricky" and "tedious" than the other, which is what I was addressing. If you code something for artistic or "competitive" reasons then of course it makes complete sense. Like people making 4KB demos, speedrunners or people folding thousands of paper cranes. There are no invalid paths if you're an artist. On the other hand if you consider it from a practical engineering perspective then there are few use cases where I'd go with ASM nowadays, well optimized C code will be easier to write, probably nearly as fast, way easier to modify and maintain and much more portable. Some paths are wildly superior to others if you're an engineer.
- rbanffy 9y agoModern CPUs are insanely complicated, with thousands of different instructions, countless layers of cruft and bewildering performance variations across architecture generations - what's optimal in one gen can be a worst case scenario two generations down the road. For any modern CPU I'd never attack a problem ASM first and, most probably, never even touch it. But we are talking about the 6502 inside the NES, running at less than 2 MHz, with one accumulator and two index registers, a couple status flags and an 8-bit stack pointer within a 256-byte stack. It's a simple machine, for simpler problems. And yet, guys like Paul Lutus were doing real-time 3D wireframes in FORTH, with fast 8-bit scaled trigonometric functions (no floats involved). It was pure badass of a magnitude not heard of since. My own contribution was a windowing library for the Apple II that did fit in 1024 bytes and ran self-modifying code to display overlapping windows.
- jackhack 9y agoYou've captured exactly what it feels like -- this is the constant tension among asm developers. I love really high performance code, but I also like accomplishing more than one trivial thing per hour. It's hard to even remember the time before I knew C, when coding in assembly was all there was. When it was "normal." But I do remember the first time I wrote for the M68000 chipset and finding a multiply and divide instruction. "What? I don't have to write my own divide routine?" Tears of joy! I will typically build something out in a high level language, profile to see where the time is going, and take a closer look at the algorithm first to see if it's sensible or some different approach should be taken. If it's an appropriate algo, then it's time to look at the implementation to see where we can shave cycles. For the most part, even if you're talking to hardware that requires exceedingly precise timing (interface/bus protocols, certain chips), C will probably do the job. (It's no coincidence it was referred to as "universal assembly language".) Only where one is absolutely starved for resources (as the NES, and many 8-bit systems were/are) is ASM necessary. "high level when you can, assembly when you must"
- deleted 9y ago[deleted]
- pjmlp 9y ago> "high level when you can, assembly when you must" I was already following that on MS-DOS with its 640 KB, with all Basic, Pascal, C and C++ compilers from Borland and Clipper. Although I did spent one year still focused on using TASM for everything and playing how much I could cram into a COM file.
- rbanffy 9y ago> "I want to iterate through the leaves of a binary tree and compute its standard deviation" Assuming this is a recurring problem, I'd just use two libraries - a binary tree and a floating point one (I cut my teeth on the Apple II+, so I could count on FP routines already in place in the ROM. If a tree library is not available, writing a tree walker is not a particularly difficult task. Libraries, subroutines and macros were a huge helper then. > I need an intermediary register, do I have one available? If we are talking 6502, the answer is "no". You had page zero, which was almost as good as having 256 8-bit registers.
- pjmlp 9y ago> I think writing assembly is a skill any coder should have, especially if you usually deal with close-to-the-metal languages like C, C++ or Rust for instance. It also applies to using languages like Java and C#. Occasional devs might not be aware of it, but there are ways to see what the JIT/AOT compilers generate.