Hacker News new | past | comments | ask | show | jobs | submit login
Some Assembly Required: An approachable introduction to assembly (github.com/hackclub)
587 points by quackduck on June 28, 2022 | hide | past | favorite | 125 comments



It was so fun working with Hack Clubbers on this project!

Hack Club is a group of teenagers from all over the world, and we decided to learn assembly together from scratch and see what happened.

We ended up making this guide as we learned, since a lot of the resources we were working with weren't the easiest to parse.

Happy to answer any questions :)


I gotta say, it's pretty cool how nice young people have it these days with what's available in terms of stuff like Hack Club. The whole scene has become WAY more inclusive as a result of things like that, and the acerbic hacker archetype who snaps at you for not knowing things the way they do is so dead as a result - that to me is great, I don't miss those guys and their gatekeeping.

If you want to check out some fun assembly code in a larger program, I suggest checking out the leaked furby source code. [1] The assembly for the lunar landing modules from the 1960s is also pretty wild [2]

[1] https://www.seanriddle.com/furbysource.pdf

[2] https://github.com/chrislgarry/Apollo-11


You just brought a random memory from uni where a small group of people wanted to get others interested in cybersecurity and did a weekly session on teaching others.. First meeting had a huge turnout and I expected future meetings to consist of learning through teaching us concepts with some practical tasks, except it became a session of just a few people talking to each other using security terminology that no one understood because it was meant to be introductory.


I think the big thing is that pedagogy itself is a hugely broad subject and especially skill that you might just dunning-kruger yourself hard on thinking you're good at. I always thought school would have been a lot more engaging if the teachers were actually paid enough to give a damn, they have a tremendously undervalued skill set and we put our kids in the trust of them while cutting their salaries every other year or so? What the hell is the motivation at that point?

I really cut my teeth on programming getting yelled at a lot by a guy in German about meeting OpenBSD kodequalität and that kind of sucked, to be honest I was at a point one time after enough workplace toxicity in IT (Getting sexually harassed by a boss at a megacorp guaranteed I don't ever want to work at one of those places again especially) where I figured I'd rather be a bee farmer or something instead. There's really no necessity for that kind of attitude but some people have been going around acting like this is the way things are in IT so you better suck it up and get used to it, especially when there's a lot of money on the line, and it's definitely true that a LOT of people could learn better on how to write code that doesn't get hacked or crashes, because often there isn't just tons of money on the line but people's health, safety, and wellness - but if the health, safety and wellness of the person writing the code is affected by some insanely stupid cultural assumption that's existed in this industry, then how good are they ultimately going to be at it in their code? It was kind of funny watching Linus Torvalds explode at people for these things back in the day, but in hindsight I'm very glad he took some time off to become a more emotionally and socially mature person for the good of the project. I don't want to work in an industry where it's just smelly angry brogrammers with maturity issues, the more that changes the better and I think I see it happening quite rapidly.

What these kids are doing is a huge step in the right direction, I applaud them. They seem to get what the past half century or so of people seem to have been kind of embarrassingly bad at and that's just being decent human beings with each other.


> It was kind of funny watching Linus Torvalds explode at people for these things back in the day, but in hindsight I'm very glad he took some time off to become a more emotionally and socially mature person for the good of the project.

It's ironic that you say this while complaining about bad attitudes in the OpenBSD community. When it comes to obnoxious attitudes, Linus Torvalds is a nobody compared to Theo de Raadt. BTW, Linus is now pushing for gradual adoption of Rust in the kernel, which would turn many issues of "writing code that doesn't crash" (though not all) into things that a compiler can check for you. That community is generally pretty relaxed and cooperative towards newcomers, due to a shared understanding that there's no point getting angry about code that won't even pass that check.


I haven't seen that out of Theo for a really long time, either. Most OpenBSD dev these days has seemed to move on from the beer hackathons and into academic/corporate dev for sure. It's all growing up. Most of my reference is relevant to +10 years ago. I like the OpenBSD scene these days a lot actually, there's a ton to learn from them. They are a lot more of a nice community than their old legacy might have you believing.

I like the Redox crowd and other people who are trying their hand at pure rust kernel+userland as well, they are doing some very interesting things that probably should have been done a long time ago - it's just not exactly easy to move on from C/C++ heterodoxy when it's such a complex thing to even fathom entirely replacing. Like when your whole kernel is in a different ABI you need to replace the whole userland, too... Not exactly small potatoes. Very admirable to just go ahead and do it.


It's so amazing, I completely agree! It's really inspiring honestly.

And... OH MY GOD FURBY SOURCECODE THIS IS AWESOME THANK YOU


Glad you find joy in it. It's 6502 assembly, in case you were wondering - Though the chip was a low-voltage 6502-alike called the Sunplus.

Those things were pretty crazy when they glitched out, my friend had one which would get thrown in into a loop where it just open and close its eyes looking from side to side going WEAOWEAOWEAOWEAO like some kind of possessed demon until you took the batteries out.

Oh yeah, obligatory picture of what I'm pretty sure is Margaret Hamilton standing next to a printout of that lunar lander code [1]

[1] https://www.nasa.gov/sites/default/files/thumbnails/image/ma...


> Those things were pretty crazy when they glitched out [...] thrown into a loop like some kind of possessed demon

I was under the impression that this is the primary memorable feature of Furbies.

The second one is the Furby Organ, of course: https://youtube.com/watch?v=GYLBjScgb7o


My favorite demonic animatronic toy must be the ol' setting tickle me elmo on fire while he starts laughing like a maniac about how much it tickles [1]

[1] https://www.youtube.com/watch?v=GYGhmJD9LKc


This is really wonderful. And I like how simple and clean the pages look, even through markdown+github. Cheers.


Thank you so much!! We really wanted to try to make it live alongside the code examples in GitHub, but still feel almost e-book like. We definitely hacked around the GH Markdown a bit to achieve this. Thanks for noticing!


I only skimmed but it's looking good so far! Would you like feedback or suggestions? And if so, using git issues or other? Thanks!


Issues and PRs are preferred - thank you so much for reading! :D


Bravo! Great to see stuff like this! Hopefully you made some new friends too.


Thank you so much! It was so fun working with the teenagers in the community.


>Happy to answer any questions :)

what happens when a member hits 20?


They’re taken away to be… replaced by someone more fit, capable, and attractive.


Echoing other's comments... I'm happy you did this and hope to see more content like it!


Hey that's awesome! When I was a teenager I learnt C++ so I could code on a Zelda fan game engine. Why did you guys want to learn assembly?


My favorite part is the heavily commented code examples. Those are much more useful for increasing my understanding than most other resources. To me, that level of information density just works better for my brain than articles or sites that try to explain things.

Something about being _in the code_ while stepping through lines one by one with explanations is just so much easier to follow. I wish more learning resources took this approach.


> Something about being _in the code_ while stepping through lines one by one with explanations is just so much easier to follow.

I just go straight to the code. Same with SO - I'm not reading words, I'm reading code. Even with zero familiarity I find code is easier to read with inline docs vs. digging through someone's word salad. Truth is most of us aren't great technical writers.

That being said I did skim the content for this resource and found it to be pretty to the point and clear-cut. Even the metaphors and extra information were applicable to providing a good primer. I wish more devs would write with the same succinct technical clarity as this and maybe I wouldn't skip the word salad as much ha


Ahhhh thank you for mentioning this! This was _really_ important to us, because it was hard for us to find real code examples that worked, and when we did, they were hard to parse.

It's also why we put it in GitHub, so it could live alongside the code examples :)


Yes! I think two things with code examples have a significant impact, at least for me personally- 1) the examples are complete and work and 2) line-by-line explanation.

A lot of resources show a snippet of code, followed by an impenetrable paragraph that tries to explain multiple concepts from the snippet all at once. Maybe that works for others, but for me it makes it impossible to parse and overwhelms me, so nothing sticks.


This 100%, i often find alot of blogs and documentation really difficult to follow because they just show a snippet and no where in the doc does it cover the prerequisites to get to that point.

I get you don't want to clutter the point, but start with a link to working code or an article that explains the basics.

I would be happy if more articles/docs explained how this code is being called.


I basically learned C++ and assembly programmer at the same time when I was 16 by just watching the output of gcc.godbolt.org (yes ok zoomer)


That's clever! I'll recommend that to my niece and daughters.


They might end up as compiler devs. Be careful...


And write parsers and llvm glue code all day long.


Don't forget test runners


That's incredibly cool to hear! I'm really excited about the upcoming generation of programmers empowered by the tools they have with them.


I'd like to share an old Dylan Cuthbert blog post on his hypothesis that Assembly is actually easier for kids to learn programming.

https://www.gamesindustry.biz/articles/2011-03-30-machine-co...


that was my experience too. An abstraction like "add" is not less complicated than "1" if both are equally new things. The number actually gives additional features. The next instruction is called "2" while in abstraction to words it is unguessable and hard to remember: unGuessAble? un_guessable? ungu? ung?


This is making me wonder just how raw Sawyer’s code for Rollercoaster Tycoon was. The source doesn’t seem to be out there but a page on his site (http://www.chrissawyergames.com/faq3.htm) says he used “MS Macro Assembler V6.11c” so it’s probably safe to assume he didn’t type out every single instruction in the game by hand. Depending on how many macros he’d built up at this point in his career it might have felt more like programming in C, except with a lower conceptual barrier to switching to inline assembly functions when stuff needed to be optimized.


MASM and the Intel assembler were already rather high-level compared to other assemblers, with a type system, procedures, records, etc. Those later versions of MASM added things like automatic allocation of structs on the stack and for loops. Depends on what features Sawyer used, but that assenbler in particular is a pretty advanced tool.


Assembly language is actually simple stuff. You just need to read the datasheet. No difficult type systems to deal with.

In the old days programming assembly language was nasty because one mistake could mean your computer had to be rebooted and you lost your work. Not anymore.


This is like saying chess is simple stuff because you can learn how the pieces move in five minutes.

If all you want is a basic understanding of how things work, that level is ok. If you want to play/program, it is a completely different story.

I'd even go so far to say: Why do assembly if your goal is not to be better than the compiler, at least in some respect? Beating the compiler, now tell me that it's simple stuff.


But chess is approachable because you can learn how the pieces move in five minutes. Contrast that with some German board games where going over the instructions is the first hour and even then you aren't sure if you understand.

Why learn assembly?, well for one, the non-abstract aspect of assembly is less abstract, and arguably easier to understand than even the simplest high level languages. Secondly, learning assembly is also learning how computers work and that paradigm will help you even as you largely work in a high level language.

And beating the compiler isn't as hard as you might think if that becomes necessary some day.


I only read assembly these days, not write it. Usually when looking at profiling outputs for my hot path. So knowing assembly is still very valuable when you routinely find your code isn't keeping up with your data, and scaling isn't an option.


Another use case for assembly is reverse engineering, even if you aren't better than the compiler, being able to understand what the compiler spit out is really handy.


A compiler’s main virtue is patience, not smarts. That’s because there’s no value in smarts; the systems like Itanium designed to need them turned out to be unusable.


Just read the data sheet!

googles Intel CPU data sheet

Ah, here we go.

https://www.intel.com/content/www/us/en/products/docs/proces...

Just two volumes and 1000 pages of reading. Simple!


Intel assembly is complex due backwards compatibility and extensions.

I've found working with a simpler, smaller processor can be an absolute joy.


I taught myself x86 assembly from a book as a pre-internet teenager. My first .COM printed exactly what it was supposed to on the screen. Then it printed a bunch of random junk and my computer rebooted. This happened every single time I ran the executable.

Eventually I actually read the first chapter properly and added MOV AH,4CH / MOV AL,0 / INT 21H. When my executable returned to the DOS prompt this time after running it, I felt like my mind had just expanded 10-fold as I realised what had been happening.


Did you get that "This machine does whatever I can tell it to do!" feeling?

And then you wonder what can you think to tell it to do. The wonder of computers.


That is an amazing feeling!

Then it hits: that crash, bug, unexpected behavior is definitely my fault!

Lol, good times when one works on a routine that executes, crashes and burns long before that finger loses contact with the "return" key!


What did cause the reboot? Is this some kind of DOS watchdog that reboots the system because your program didn't exit gracefully?


Or? MOV DX, 200 / INT 27H


Assembly is simple if all one does is printing hello world (even that is actually not trivial, because one needs to know/read the syscall and the ABI).

Anything beyond that gets complex quickly, in one way or another. On simple architectures, like the 6502, even doing a simple division is complex (heck, even additions are verbose, since 8 bits are too few for a lot of operations). On more complex architectures, like x64, there is a monstrous ISA full of inconsistencies.

Learning assembly as in learning an instruction set also doesn't include a lot of details of computer architecture, although at least some modern assembly books mix both domains.


It's simple in the same way C is simple. Sure it's a very small language with pretty straight forward commands, but once you try doing anything of significance it becomes extremely complicated and it's easy to do nasty things with it.


It may be simple but that simplicity is its downfall. How many databases, compilers, modern games. OOP classes or even file handling routines do you see in assembler? Few or none at all. Writing assembly language is slow and painstaking work. You can easily get 10x the productivity by switching to C or even better in higher languages. Games were written in assembler back then because Basic was too slow. And C compilers were only starting to appear on personal computers from the late 1980s.

Writing an assembler for 8-bit CPUS like 6502/Z80 was doable; I wrote a 6502 cross assembler (in Z80) so a Z80 development machine could output 6502 in 1985. It got harder with 8086 and 68000 chips.


You still need to learn a lot of stuff. Problem is that it isn't portable. You have differences in architectures but most are quite similar if your goal is to make a program work instead of it being efficient for which you need deep knowledge about an architecture and its quirks. A few different mnemonic and register names is the far smaller problem.

But you also need to know about calling conventions of your operating system if you want to do any form of system call, which you very likely want to. Which registers supply arguments, which registers have to be saved, addresses of system functions which can change with OS or kernel version. You also need to learn what these function do. How would anyone know that writing a 48 into your accumulator and calling interrupt at address 80 opens a socket on Linux?

Thinking about this again makes assembly seem like a terrible, terrible idea...

To start with I would either recommend x86_64 for either Windows and Linux. I would prefer Linux here but I believe UEFI for example uses the Windows calling conventions, so taking a look at that might be practical. But these combinations usually offer the most learning helpers.

Usually you should only cause general protection faults at worst if you have something newer than a 386. But no guarantee...


The big hurdle for me was always understanding where assembly language ends and the assembler directives begin. That and the “now what?”, not knowing how to make a program do something interesting - needing to learn about the ROMs, the OS, etc.


I may be very out of date, as my last assembly language programming was in 80386 days - but types are important in x86. You definitely need to know your words from your bytes, and your index from your offset.


I was worried this was only going to be a discussion of x86 assembly. Pleasantly surprised it included 6502 and RISC-V. It's worth reading even if you're not a teenager.


I'm glad you liked it! By a teenagers' guide I meant it was written by teens (including me: I'm 17). What do you think of the warehouse analogy?


Can't speak for the OP but I really liked it. It reminded me a bit of the computer game Human Resource Machine[0], which creates a mini assembly language that you use to handle a "production line" of incoming numbers.

[0] https://store.steampowered.com/app/375820/Human_Resource_Mac...


This is a great way to accidentally learn assembly language! I was so amused that a designer friend of mine who swore they could never learn to program solved this game and in certain cases, more optimally than myself, and I have a fair amount of experience in assembly.


I love it! There's also a mobile version apparently.


ooh thanks for sharing that game


What a remarkable group of people you are.

Also I didn’t realize Rollercoaster Tycoon was primarily written in Assembly. That’s nuts.


Steve Gibson (grc.com) uses assembly for most (all?) of the software he distributes.

For example, his DNS Nameserver Benchmarking utility[1] is 160 KB and when you download it, it's a single uncompressed executable and has a decent win32 UI. It will run any version of Windows going back to Windows 95.

Could you even run a mid-90's era macOS or KDE+Linux executable on a current Mac or Linux machine? (I don't think Gnome even existed yet).

[1]: https://www.grc.com/dns/benchmark.htm


Not great not terrible. Analogies aren't that useful IMO, so it's cute but might not be a useful pedagogical aid.

Conceptual flaws (mainly down the line rather than introductory):

One issue with it down the line is that processors spend a lot of their design budgets avoiding carting memory around. You don't have to mention that explicitly but in my skim reading I would've (if I were writing it) tried to emphasize something more akin to a postal sorting room than a warehouse as per se.

Maybe that's too advanced, but I understood it when I was 18 or 19 so YMMV.

One interesting demo is to see how much assembly you can fit in a single memory access latency.


The warehouse analogy was great. You and your co-writers did a fantastic job.


Good stuff. A fine reminder that illustrations go a long way; well-done on those, and the guide as a whole.


This is amazing! Love the simplicity and the art used to explain things.


> why the Rollercoaster Tycoon creator would write 99% of the game in it

Not sure how true it is, but I heard that keeping track of a lot of objects required plenty of optimization, and apparently such levels of detail may have not been in games before. RCT was the second Tycoon game by Chris Sawyer, after Transport Tycoon from 1994—which is also in assembly and which keeps track of buses and trucks each with its own parameters, trains with each car, signals on the roads; of every passenger and every batch of goods: where it's from, how long it's on the way, etc. (At least if OpenTTD recreates the mechanics faithfully.) You can also pop up several windows with views to different parts of the map or following various vehicles.


This is great!

As a developer who didn't learn via a scholastic setting, taking the time to sit down and learn a bit of assembly was something I see as a critical point in my career.

Starting with a high level scripting language, my brain had a hard time dealing with so much abstraction and taking what felt like a crazy amount of axioms as given.

I took a few months to sit down and go through the excellent book Programming From the Ground Up. After doing some bit twiddling, writing a basic allocator, and a handful of the other exercises from the book, I felt way more prepared to handle abstractions higher up.

Anything that I couldn't infer based on the underlying knowledge was something I could google, then quickly form the missing links between starting from the bottom.

I feel like learning C could give the same benefits, though I do hear some struggle with pointers, and in assembly you get to look face first at what they actually are. Everyone has different levels of abstraction that they're comfortable with as well. Assembly was enough to fill the seeming void of knowledge that I felt was holding me back, but for others it may be higher depending on which aspects are puzzling (memory management, intermediate representations, etc).

I also appreciate how much information modern VM authors publish about the inner workings of their platforms. It helps a lot in the same manner to reason about the systems (v8, JVM, CLR, etc).


Having started my career at Bell Labs in 1984, the fact that you included AT&T X86 syntax cracked me up.

If you are still interested in learning more, ARM and PowerPC are also both interesting assembly targets.

Prior to Bell Labs (college) my assembly experience was 8085 bare metal (no OS) or Z80 under CP/M and MP/M. I wrote a couple console management applications for MP/M that had to dig into BIOS/BDOS routines. It was fun, and that was the thing that made my EE self realize that I wanted to work on software in embedded systems.


Love this! Must admit, my favourite part of doing a CS degree was creating a CPU core from scratch (a cut down ARM, running on a FPGA), then writing asm to run on it. So satisfying knowing I made the actual CPU (at gate level) and ran my own code on it. I’d be happy to do a YouTube series covering how to do this if anyone is interested.


This MIT OCW takes a student from basically nothing to an almost compliant RV32i, complete with videos, worked examples and lecture notes.

https://ocw.mit.edu/courses/6-004-computation-structures-spr...


Check out Ben Eaters youtube channels https://www.youtube.com/channel/UCS0N5baNlQWJCUrhCEo8WlA - He builds similar, and offers a kit for sale at (from what I can tell) a reasonable price, so you can also DIY.


The article links to a cool project I never heard of that does a similar thing - From Nand to Tetris[0].

[0] https://www.nand2tetris.org/


Yes please


So probably a really dumb question, but given that assembly has a limited number of operations and a limited number of registers, what are processors doing with the ever growing number of transistors added to them? What is processed with billions of transistors that can't be done with thousands?


It's not a dumb question, but it's so broad that it would take at least an entire textbook to fully answer it.

Just off the top of my head, some possibilities are:

* More cores

* More numerous/powerful execution units that can do e.g. vectorized math

* Architectural features such as virtualization and security defenses

* Bigger and more flexible caches

* Complex pipelining/out-of-order/speculation logic that allows more instructions to be executed (on average) per clock cycle

* Special-purpose functional units that dramatically accelerate particular applications (e.g. AES encryption, video encoding/decoding) and are idle the rest of the time

* Replacing "deep" networks of logic gates with equivalent "wider" ones, which occupy more die area but have a shorter critical path, enabling faster clock speeds


1. Modern CPUs have a larger internal register file and dynamically remap the logical registers referenced by machine instructions into physical instructions.

2. Modern CPUs have a very complicated instruction reordering mechanism and data dependency analysis mechanism that allows CPUs to execute multiple instructions in parallel, when it's possible.

3. A lot of transistors are used for caches (instruction and data caches, and other kinds of buffers like the one used for branch prediction etc).

4. Even a single core has multiple copies of the execution units which allow to execute some instructions in parallel (see above).


The sibling comments cover the bases really well, but just in case it's not obvious, what you are thinking of as a relatively simple machine - with a limited range of operations and registers - is actually itself an abstraction.

You see the machine executing a sequence of instructions, and that is exactly what happens - eventually.

But behind the scenes, the goal of the hardware is to execute those instructions as quickly as possible. Since there's a limit to how fast silicon can work, the way to achieve this is via a number of tricks that effectively throw yet more circuitry at the problem, taking you from millions to billions of transistors.

Just one of these tricks for example is caching. Instead of writing directly to memory (as it appears to your assembler code), the CPU actually writes data to the L1 cache, a smaller but much faster block of memory on the CPU itself. At a later time, the data can be transferred from the cache out to RAM. In fact a modern CPU will have caches feeding into caches - e.g. CPU feeds into the L1 cache, which itself feeds into the L2 cache, then into the L3 cache, and finally into RAM. At each step, the cache gets larger and slower - so while the L1 cache is measured in KB, the L3 cache in a modern CPU might be up to 64MB in size.

You don't see any of this when you are writing assembler code. To all intents and purposes the caches are invisible to you. There are obscure instructions like CLFLUSH that provide very limited control of the cache but these are not typically something you'd use.

It's easy to see how managing these caches enormously increases the circuitry in the chip, without any need for you, the assembler programmer, to even think about them.

As other commenters have noted, other areas where extra circuitry is thrown at the problem include area is pipelining. In your mental model, the CPU is probably plodding along executing instructions one after another. In practice the CPU is aggressively trying to reorder those instructions and execute them in parallel as much as possible. This is an incredibly complex process, requiring enormous amounts of circuitry.

TLDR; what you see as a relatively simple CPU instruction set is really an abstraction - behind the scenes is an enormously complex collection of moving parts that break your code down and try and execute it as quickly as possible.


Multiple CPUs, Pipelining, multithreading, onboard graphics, Apple's efficiency and machine learning cores... and multiple CPU cores, as well. The code demonstrated in these examples is essentially executed as a single thread in a single core. Modern CPUs are faster not only because of faster clock speeds, but more CPU cores and peripheral stuff, like cache memory and more, on each chip. Packing the transistors closer together means there's less distance to travel between, for example, the CPU and the arithmetic logic unit, or between the CPU and the on-board cache memory.

And I'm sure I've barely scratched the surface.


Among other things - larger caches, more instructions, more cores and more busses in between them.


I enjoyed learning assembly in college -- to me, many of the non-intuitive aspects of abstract languages make more sense when you know something like C, and C makes a lot of sense once you know assembly. It all sort of clicks in a very satisfying way.


They mentioned Z80 but do not have the examples of Z80; maybe in future might be added.

I have used some assembly language stuff, including 6502, Knuth's MIX and MMIX, and virtual codes such as Z-code and Glulx.

I have written small amounts of old x86 assembly code (for the older 16-bit PC), too. (I think that the new x86 is too messy and too complicated, compared with the old x86 which is not bad.)

I have been trying to learn TRON assembly code too, although I cannot find enough information. I found some documents, but they are in Japanese and some important diagrams seem to be missing. There is some English documentation too but it does not explain much.


Great work, very methodical!

In using assembler I find the hardest part is to represent the task at hand into a form of a sequence of elementary operations over the dynamic set of data pieces and their locations.

Perhaps, when the problem scope is on a lower level with a limited sets of data and operations, this maps easier. But when the task is on a macro level, that extra step of mapping the context onto a lower level scope is just too much effort.

In a way, in a higher level scope the programmers create their specific 'assembler' with a different set of registers and opcodes and sequences of operation, and even busses.


There was a coding competition at a local podunk BBS back in ~’91. I figured I would use it as an excuse to learn some assembly. The goal of the challenge i entered was to find all of the prime numbers between one and a million. Of course my goal with the assembly approach was speed and executable size. In both of those I smoked the competition by 3 to 4 orders of magnitude.

But the scoring mechanism was heavily weighted towards lines of code and the turbo Pascal entry one even though it took about six minutes to complete.

That pissed me off so much I never really messed with assembly again.


Get this, an old greybeard I worked with told me managers used to harsh on LoC at companies like IBM back in those days as a measure of productivity. Like people got fired over what you lost the contest on. Insane, I can see why that would tick you off


Well, if LoC didn’t count you could just write a gigantic multi-megabyte print statement :)


Or maybe have the object code for the executable as one static constant and jump to it on the one and only line of the program: speed, size and one line of code (maybe two depending on how the counting is done)


That's thinking outside the box! xD


These days you could use a language with compile-time macro execution like nim or D and have it both ways…


I think Pico-8 recently added support for editing assembly operations.

Also there is a book called Programming from the Ground Up that starts with assembly and moves up to C and beyond.


And it's inexpensive, too! Will be ordering this. Thanks!


Great work! There’s a typo on the 6502 page, DNC should be DEC for the Accumulator. Started coding asm on the c64 as 10 year old kid. Would have loved resources like this!

https://github.com/hackclub/some-assembly-required/tree/main...


Thank you!! Just yesterday I was googling trying to find a good introduction to learning assembly and today here it is!!!


This is fantastic!

I’m definitely not an assembly guy, but it would be fun if there was a REPL to play with this. Not sure if that would accidentally invert the universe or it’s too low level for a REPL, but conceptually it would be fun to play with in a sandbox.


Learning assembly has been on my wishlist forever. . . excited to give this repo a look see.


Definitely do it! Working with assembly demystified a lot of questions I had working at higher level languages (like C and Python).


Thanks for good resources about Assembly, I’m learning source code of AsmBB [1] - a forum written in assembly x86 :D

[1] https://board.asm32.info/


The most proud of assembly program I made was Voracity game (2008). The learning process was so smooth because there are only few things to use. Mind blowing moment is when I made chain jump to workaround out of range jump.


Pardon, but the assembly code on the "Loop de Loop" chapter currently seems broken. "rax" is acting as all three variables somehow.


Nice catch! Just to be clear, it was that we were incrementing our exponent but not our counter, is that right? I pushed up a fix, but let me know if there were other issues.


It's a bit more involved than that.

  mul rcx, rax       ; multiply our result by our base, save into rcx
This should probably be using rbx, since that's the designated base, not rax, which is the exponent.

In the explanation just above, there's a 2*8 step missing, while this one is incorrect:

  4. result = 16 * 2, result is now 16
Since 2*16 is not 16.


Ahhhhh thank you! Do you mind opening a PR or issue so I can get to that? Thank you for noticing!!


very nice! I wouldnt give this to a programming novice but its very nice for people who know their stuff and just havent done asm yet.


Thanks! Totally agree - you need to understand some programming basics in order to understand the examples in the code section. Things like variables and for loops.


Good job. Some constructive criticism:

There's quite a big difficulty spike so to speak in the later section as you go towards the code examples. The beginning explains relatively simple concepts like binary, then basically jmps into an instruction table which won't make sense to anyone who hasn't done some form of programming (they would know binary then, right?).

The tone is also a bit off putting, although I might be out of touch with today's teenagers. When I was learning asm as a teen I learned it from grungy 1337 h4x0r sites (well, they didn't actually use 1337speak except ironically, much like today) which were at least a great deal.. meaner? less nice?.. than the tone of the article.

From what I wrote I gather my main criticism is that it doesn't know its audience. However, it seemingly _was_ produced by an actual group of teenager as per the author's HN comment:

> Hack Club is a group of teenagers from all over the world, and we decided to learn assembly together from scratch and see what happened.

Although it probably means a trained adult was lightly helped by some teenagers in producing it.

I hope this didn't sound too harsh, the effort is very good and so are the illustrations. It needs some fleshing and perhaps a little less "yay!!". Learning assembly is not actually that fun, it's rather painful. It's what you do with it that is fun.


> Learning assembly is not actually that fun, it's rather painful. It's what you do with it that is fun.

As a teen, I taught myself assembler circa 1982 on my Radio Shack Color Computer (with 4k of RAM!). It was indeed painfully challenging, especially due to the complete lack of information available and the fact I didn't know anyone else who knew anything about it. The only reason I persisted was that the BASIC interpreter in ROM was too slow to write any really cool games. The other thing that kept me going was that assembler was arcane hidden knowledge which bestowed power on those who could figure it out. I didn't want to "learn" assembler, I just wanted to use it and that required knowing how it worked.

I succeeded only because my teenage self somehow pulled off a phone call to Motorola sales where I claimed to be an engineer "evaluating" the 6809 CPU and they sent me the manual and a quick reference card. Due to my complete lack of background in computers or electronics, the manual was pretty cryptic but that quick reference card was my constant companion that entire Summer as I used the BASIC PEEK and POKE commands to write programs. I ordered a "Monitor Program" from a small ad in the back of a garage-published computer magazine. When that cassette tape arrived it allowed me to actually read and write assembler mnemonics into memory, set breakpoints and look at registers. The next breakthrough was realizing I could use it to examine the ROM assembler code. When I finally convinced my parents to buy a dot matrix printer, I printed the entire 8k of the BASIC on fan-fold paper and went through it, commenting by hand.

To your point, the fact that it was so hard combined with it being arcane knowledge was perhaps what kept me going. That and the reality it was the only way forward to get the computer to do more cool stuff.


You put it better than I did. I'm younger than you so I had IRC & phpBB to lean on, but that still meant clawing out the advanced knowledge from the hands of the elders. It's where I learned that the best way to get a real answer is to first say something wrong. But at least smart enough to get a response.

The feeling of mysticism and challenge is dispersed when put into an easy to grasp format. This enables more people to learn enough to reach the skill floor, but it doesn't teach those with an able mind to reach for the ceiling. I see this nowadays a lot, most people around me who didn't grow up with this culture are much worse debuggers. That's not because of their technical skills, but a lack of tenacity. Having answers be far far away means that when you start finding them regardless, you gain an inner mindset of "no matter how hard this is, eventually it is understandable". Seeing what other people could reverse engineer with extremely poor resources inspires one to try harder when there's no solution in sight. It's also taught me that I am _nowhere near as smart_ as I thought I was. To a hilarious degree. Somehow this is not a paradox.


Very well put! Although I didn't know it when banging my teenage head against assembler, throughout my long career in tech I found the combination of tenacity, humility and "down to the metal" sense of how computers work served me very well.


> I succeeded only because my teenage self somehow pulled off a phone call to Motorola sales where I claimed to be an engineer "evaluating" the 6809 CPU and they sent me the manual and a quick reference card.

lol that is such a nice story


Moto and the other large semi vendors back then had data departments that would send you any datasheet on request. My teenage self made many such requests, but in writing in order to not reval my age (in snail mail, everyone's an adult).


Yes. Around 1994 when I was in college, a friend and I were into video graphics and Intel had a video digitizer chip. We wrote to Intel (snailmail) asking for the data/spec sheet and about two months later, we received a packet with about 120 pages of the data/spec sheet.


Yeah I miss when programming felt cool and badass rather than like I was in a HR training seminar


> When I was learning asm as a teen I learned it from grungy 1337 h4x0r sites (well, they didn't actually use 1337speak except ironically, much like today) which were at least a great deal.. meaner? less nice?.. than the tone of the article.

Which ones?


Phrack & hackthissite mostly


[flagged]


What do you mean by "pronoun-hedonism"?


There is a style of hedonistic lifestyle/culture that usually comes with an anime profile picture and pronouns in the twitter bio. If that is someone's true "form" then go for it, but when its fake yuck.


Gratuitous anime pictures are also common in 4chan tech culture, where folks just don't pay much attention to Twitter or to the pronouns fad. So you can see that either way, it just suggests a kind of non-serious/poser hedonism all around. BBS/early web culture was a lot more focused than that.


Those illustrations are gorgeous.


Very cool! Amazing work you all!


Wonderful. Love the rich comments in the code.


"Since forever ago, I've wanted to try writing assembly, even if just to understand why the Rollercoaster Tycoon creator would write 99% of the game in it. To be fair, even after all of this, I still don't understand why they did that."

Hubris?


I doubt hubris.

Frankly, depending on their experience, assembly may well be familiar, efficient and effective.

Some people who got going early on in games, in the 8 bit era, went right for assembly language because that is where the speed necessary to make magic happen on the screen was.

Action / arcade games pretty much demanded it, unless they sharply limited what happens on screen.

You might find some of the early stories informative. Nasir, for example, did his first dozen or so games with the mini line assembler in his Apple 2. No source code, no labels, etc...

https://youtu.be/S3EmtTpoEa8

On some of the projects I did on 8 bit computers, it was all about assembly. One planned out a few things, worked around where the screen was, or needed to be (depending on hardware capability), on screen graphics, other data needed, and then build in chunks, saving stuff off to disk.

Every so often, load several in, tie them together, save that off, then run it. It is a different style of thinking for sure.

I bet that developer knew how to build something up that way and went with what worked, was performant, and that was probably the easiest path for them.


this is damn cool!


Finished?


this is really cool




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: