A year ago, while reading a post about security, I came across Embedded Security CTF. It's a game for teaching about reverse engineering. I played a couple of levels and it was actually fun. But what it made me remember is that Assembly is actually simple.
My motivation in learning how to program came from how I wanted to be a hacker. I've read "Hacking: The art of exploitation" from Jon Erickson which encouraged me to widen my knowledge about computers. I've also read "The Shellcoder's Handbook" and "Gray Hat Hacking" and I remember struggling to get past the first part of these books. You have to understand the basics of how programs work and while they did a great job summarizing that, it was just too alien from what I knew. It was actually too basic.
My first languages were C and Python. And while C is a low-level language compared to Python, it still adds a lot of abstractions over Assembly. Functions, variables, looping,... don't exist in Assembly. And my thought process was wrapped around these concepts. It went better after I learned how those abstractions are implemented when the code is translated to machine code.
What I did understand is that, once compiled, your code will actually be a mix of data and instructions (which are special data). Those instructions can be roughly grouped into three categories based on what they do.
One of the most common instructions
MOV falls under this category. You actually do that a lot, moving data from a location (memory, storages, registers) to another one. Even when displaying something, you're just moving data to the graphics controller.
Other instructions like
CMP do that. While they may involve complex circuits (Like when doing floating point arithmetics), what they do is doing basic operations like addition, division and storing the result somewhere.
The processor actually executes code in a linear fashion, one instruction after another and there's a register for keeping track of where the next instruction is. By manipulating the value in that register, we can skip over instructions or go back to a previous one.
CALL and other instructions do that.
That's a very rough overview of what Assembly is. Some assemblers add their own abstractions over it. Assembly is simple, but it can be tedious to write and even read. That's why you have all those abstractions in high-level languages that are closer to how we think instead of how the computer works, making code easier to understand.