Ask HN: How to begin learning assembler for university course?
Next semester I'll have a subject about computer architecture. During it, we'll be learning assembler (TASM, if the website's correct).
Could I ask for your advice, how to approach that topic? I'm not going to lie, task of learning assembler seems to me quite daunting and stresses me out. Do you have any tips from your personal experience? Do you have any TASM books recommendations?
63 comments
[ 4.1 ms ] story [ 142 ms ] threadWhen I was in the uni we had a forum for all years where we shared info on subjects, lecturers and info needed in general. I don't know how students do it nowadays probably via messenger, whatsapp and gdrvie links.
But to be honest, just approach it like any other language.
- Learn the basic constructs (control structure patterns, loop patterns and instructions etc)
- Use it to solve easy problems (something like the easy problems in project euler)
- Just read source code to see how people use it in c/c++ programs.
In general TASM is pretty limited, but the knowledge you gain there can be used in other places which makes it worth it.
Edit: Formatting
So, how about starting out with a C program that enters main, calls an extern assembly function and then exits? And this would be the example C code:
Now you have to create your assembly file, and then compile it to an object file that can be linked with your program: OR See: https://www.ele.uva.es/~jesman/BigSeti/seti1/nasm/nasmdoc2.h...I've never used TASM before and I couldn't really find anyone using it. But I guess the course will cover that. Is this programming on Windows or Linux?
Considering that it's TASM it's good old DOS.
For that you'll need to setup some sort of environment where you can write, assemble and run your assembly code. jakuboboza has some good ideas to check with previous students to know what can of environment you need.
Eventually you can check an even simpler assembly like the 8051 that has very simple emulators and IDEs available. Or, if you want something a bit more game-y you can look into Zachtronics' puzzle games[0] that often have an assembly-like language and come with a manual, which can help you become familiar with the basic principles. TIS-100 is only assembly writing, Shenzen I/O has a bit of wiring/"electronics" on top and EXAPUNKS makes you "hack" systems using little bots written with this assembly.
I found that knowing a bit of assembly is quite useful and interesting to learn, I hope you'll have fun with it !
[0] : https://www.zachtronics.com/
Thank you too
Did someone tell you assembly is hard? I will tell you that assembly is easy, very easy. It's easy because instructions are simple and stupid. They do one little thing, and maybe set a few flags. And while modern ISAs have grown a ton of cruft, you get pretty far with a small set of core instructions (loads & stores, register-register and immediate-register moves, arithmetic, testing flags, branching). Given that it's a computer architecture course, they'll probably want you to learn something about ABI and calling conventions too. Not a big deal, it just illustrates the (somewhat arbitrary) convention of what to pass in registers vs what to pass on stack, who saves registers (which registers?) and so on. Simple stuff that you just need to have a convention for if you want to make it easy to interface with prebuilt binaries.
With very basic knowledge, you could disassemble a program and just look up instructions as you go to figure out what it does. That is how I "learned" assembly. I put learned in quotes because for me learning is on-demand and is never fully done. I learn more as I need, including last week when I did some ARM assembly programming.
I think assembly has an undeserved reputation for being difficult, because building large programs in assembly is a lot of work. Also because fear of the unknown: few people learn assembly, and even fewer use it enough to be proficient with it, so in their mind it's the devil they don't know. I doubt the course has you building large applications, it'll be some rather basic things. And that's how a lot of assembly usage is in real life: you just have to do some basic bits in early stage bootloaders, OS kernels, crt, etc. in assembly. But only enough to get the code in a higher level language going. (The other significant use is in optimization, especially SIMD, but I doubt a computer architecture course would focus on that too much).
Have no fear and just dive in. That's how you approach the topic.
Knowing C and checking the compiler output is very helpful. You can do it interactively on godbolt.org, it'll even hilight lines and the corresponding machine instructions.
It is difficult. But you put in the work and like anything it gets easier. My first experience was learning 65xx Assembly on my own when I was 11. I think OP will be just fine.
I didn't think it was particularly difficult. Of course, starting from scratch, there was a lot I had to look up and thus it was rather time consuming. But at no point did I feel it was hard, I just needed to push on.
I like assembly, but the idea that assembly is easy is not realistic.
On one end, there are CPUs like the 6502, which have a stupid easy instruction set, where making anything that is not trivial is complex due to lack of register and instructions - even divisions and multiplications.
On the other end there are have modern ISAs like the x64, with the (understandably) complex SSE instructions, and all the idiosynchrasies/inconsistencies of the instruction set due to legacy.
Probably a sweet spot (complexity-wise) is the 16-bit 8086.
But even that, programming and/or understanding programs means knowing system calls and/or documenting them very clearly, which is a significant amount of work. ASM is difficult (also) because abstractions are paper-thin.
With that in mind,
> I doubt the course has you building large applications, it'll be some rather basic things. And that's how a lot of assembly usage is in real life: you just have to do some basic bits in early stage bootloaders, OS kernels, crt, etc. in assembly
I definitely agree with this, and the OP could relax, as the application of Assembly they'll likely work with is going to be (relatively) comfortable.
By assembly, I mean the general idea of machine instructions, which you find on every computer. It is simple and quite easy. It doesn't matter whether you start on x86 or amd64 or arm or whatever; the basics are very similar and quickly learned; a handful of instructions are needed for turing completeness and you can ignore most of the rest. You know and understand assembly in general even if you don't know every instruction on amd64 and avr and arm. When you need more, it's just a matter of looking it up.
I'm not saying that learning all of a complex instruction set is easy, but that's more "learning the ins and outs of a complex platform is a lot of work" than it is "assembly is hard." System calls likewise are platform complexity more than they are assembly difficulty. Same for all the hardware registers and peripherals if you're doing bare metal programming as I am.
This is an idea that assumes spherical instructions in the void, in other words, just passively staring at a listing (or at most, writing a hello world).
On a simplistic ISA like the 65xx, it's very complex to handle arithmetic as simple as a division or multiplication.
Implementing them is hard, and reading them is hard, too ("what is this code doing"?). There are multiple implementations that one has to know in either case, otherwise it takes a considerable time especially when writing them.
Anything beyond a "hello world" is definitely complicated in ASM.
Writing a bootloader or memory allocator or atomically flipping bits in a peripheral register would be hard in Python, but that doesn't imply Python is hard in general. Making performant and carefully timed code (for example, bitbanging a protocol) in CircuitPython can be hard. It's not the language, it's the thing you're trying to do with it.
Doing floating point math in assembly on an 8-bit AVR is hard but that doesn't make assembly in general hard, it just makes the thing that isn't particularly well suited for the AVR platform hard on that platform.
On a similar note, assembly can make many things easy that are complicated to do right in C due to implementation defined or undefined behavior. Or sometimes simply due to lack of suitable operators or standard library functions (e.g. popcnt).
I'm trying to point out the difference between the thing you do and the thing you do it with. I still hold that assembly is easy, but you can find things that are hard to do with it. Nailing a plank is easy, building a plane out of nails and planks is not.
I have seen plenty of nontrivial assembly programs that by and far rely on a small set of simple core instructions and don't need to go to great lengths to work around platform limitations. They do things that assembly is well suited for, and then use another language for things assembly isn't well suited for.
Without complaining a lot, that's not given. One of the professors supposedly is very helpful, while the second one... not so much. And here I cannot "choose" professors, it's pure luck. Okay, enough complaining.
I dread it still a little, but I'm also at the same time wanting to start that as soon as I can, as it... I'd lie if I said assembly isn't interesting. And I want to see what's that all about.
Thank you
That said, Compiler Explorer [0] is very useful to see what modern compilers actually do. If you want to learn how simple programs are converted to assembly, make sure you turn off the optimisations with the ‘-O0’ compiler flag.
[0] https://godbolt.org/
https://8bitworkshop.com/v3.9.0/?platform=c64&file=hello.das...
It's mostly vintage CPUs like the 6502 or Z80, but those have the advantage that they're trivial to learn, and the basic concepts still apply to modern CPU assembly.
There's also a DOSBox wrapper for x86 assembly though (sadly nothing 68000 based, because this was by far the nicest CPU for assembly coding).
His youtube videos are interesting as well.
https://www.amazon.com/Mastering-Turbo-Assembler-Tom-Swan/dp...
If the university is any good at teaching, it will pace the course in a way that at least ⅔ of the students will be able to follow the course. If you have time _this_ semester to read a book about _next_ semester’s stuff, you aren’t struggling to keep up, so I would expect you to be in that group.
Also, assembler breaks down stuff into smaller steps, but that doesn’t mean it’s hard. It ‘just’ makes it more work to write large programs.
If you have done some C programming, assembler is a bit like having a program where you declare a fixed number of integers (say A, B, and C) and a fixed set of double's (say D and E), a huge array of bytes called MEMORY, functions for reading bytes and integers from, and writing them to it, and then limit your program to.
- simple expressions (e.g. A=B+C is fine, A=B+C+D isn’t. You would have to do A=B+C; A=A+D; instead). The exact set of allowed things varies by CPU. Some allow you to do “A=B + MEMORY[C], some don’t, etc)
- not using while, for
- if is only allowed as if A op 0 goto FOO; (where op is ==, !=, <, etc)
The exact set of int's and double's and the set of allowed expressions varies by processor. also, assembler syntax is different. you'd write something like (this is different per processor, and even between assemblers) "ADD A,B,C" for "A=B+C", for example.
You could start with a small C program and see whether you can change it to adhere to some of these restrictions.
Sample programs could be
- computing the GCD of what’s in A and B
- counting the number of times each byte value occurs in MEMORY between offsets 10,000 and 20,000.
- checking whether the memory region between offsets A and B contains a range of values equal to that given by offset C and number of bytes D.
The result won’t look like assembly, but I think it would give you the right mindset.
This is generally true, but sometimes universities assign lecturers who are poor at teaching (e.g. just reading from the slides, or alternatively not putting effort into making the material more understandable). In these circumstances, a more independent approach to learning the subject can be quite helpful (e.g. focusing more on the textbook, and designing a specific learning strategy that's independent of lecture quality).
At uni, we didn't learn to write assembler until we'd already been taught about Boolean logic, finite automata and RISC processor design. So we were already familiar with basic processor operation before writing any code for it. But I studied electrical engineering, not computer science.
Knowing your current background/field of study is going to be essential to give useful recommendations, I think.
I have background in both C and C++
What's daunting about assembler is not the concept itself, but the lack of higher-level features that allow you to maintain good structure for your code. But that won't matter for a university course, you won't be asked to write millions of instructions by hand.
I don't know what instruction set will be used in your class, but since you mention TASM I'm going to assume it's Intel x86. That architecture is a pretty wild beast to code for, for one because it's a CISC architecture, which means that there's a multitude of instructions available that duplicate and extend the basic operation of other instructions. On top of that, it has seen many revisions, enhancements and extensions over the years. If I were teaching such a class, I would probably choose a RISC architecture instead (MIPS, 8051 or nowadays RISC-V), just to reduce the size of the instruction manual the students might encounter. But it's a pretty good guess that they will be focusing on the easier, lower-level instructions only.
At least the succinctness and completeness of any instruction set manual will be a breath of fresh air compared to the level of documentation you're used to from C or C++ libraries.
At the time, I believed that if you focus on learning, the marks will come, but soon saw the results that this isn't necessarily true.
[0] https://www.youtube.com/watch?v=HyznrdDSSGM&list=PLowKtXNTBy...
I would get ahold of the TASM manual early and give it a read through, then take your x86 instruction reference and write each instruction on a 3x5 card in the proper format for the assembler and what registers the instruction changes (directly and via conditions). You'll be fine.
I'm pretty sure there is no equivalent of the IBM 360/370 banana book.
https://www.cs.virginia.edu/~evans/cs216/guides/x86.html
I didn't buy it. We should have used real processors or, at least, those fantasy processors should have been reflections of real ones. I thought then that we should have started with 8-bit processors.
Anyway, later we had a chance to do some work with real 8086 assembly and that was a lot more exciting.
I have to say I don't remember a lot, and the only difference between my theoretical knowledge before "how does assembly language roughly look, how is the control flow and how do you use it" (mostly from trying to understand cracks and binary patches for nagscreens) versus using it on a real (emulated) thing was pretty small. And most of all, I remember zero of the details now.
So yeah, maybe it would have helped you if you actually had fun, but to me it didn't really make a difference, because even back then writing assembly for speed in a modern processor was already so different that it didn't matter for the basics.
It's a lot of work to do complex things, that's for sure, but it isn't in any way hard to understand. There will be a reference guide for your processor which will be exact and succinct.
It's the easiest language there is to learn. It's hardly even a language. Even if modern processors have layers of abstraction to them, you still get to get to program a processor directly.
Don't be surprised if you also get a much better understanding of how some common data structures work when you have to code them yourself. I remember being baffled by pointers but after coding assembly a few times it suddenly seemed completely natural. It was a few years ago though.
[1] https://godbolt.org/
Note: It supports more languages than C and C++, but with the exception of Zig, the others will typically have more complicated assembly output.
Definitely not along the lines of what you're going to be taught, but fun.