As it turns out, assembly language – commands (or "opcodes" to give them their proper title) that are only one step removed from the actual instructions executed by the computer's chip – is both extremely simple and ridiculously hard. Almost everything you do is concerned with moving values around in memory, storing references to particular parts of that memory, and juggling those values and references in between a few 'registers' until you've moved the value you want into the place it belongs. There are no shortcuts, no libraries or include files; if you want some graphics to appear on the screen, you need to update the corresponding section of memory with the bitmap values that represent the thing you want to draw – and then update some other piece of memory with a value that represents the foreground and background colours for that part of the screen. Want to make it move? Just keep track of where it is, redraw it every frame ... and don't forget to undraw it from its previous location before moving it somewhere else – oh, and do that for every single moving thing on the screen.
Once you understand the basic underlying concepts it does become a little bit easier – pushing and popping things off the stack, and how to think about loops in a different way were some early stumbling blocks – and you can look at a game like Jetpac and understand what might probably be going on under the hood. But looking at something more complex, like the 3D environments of Head over Heels, and at how many lines of code it's taken me to just print a countdown from 10 to 1, and it's easy to be more than a little daunted by the task of making an entire game on your own.
Still, if 15-year-olds in the 80s could do it, without even the benefit of the internet, I'm sure I can fumble through with the help of YouTube tutorials and PDF guides.