Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Ask HN: How to begin learning assembler for university course?
41 points by _lnwk on Jan 24, 2022 | hide | past | favorite | 63 comments
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?



The notion that assembly language is somehow difficult is just silly exceptionalism.

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.


ASM is ridiculously shallow, but broad. You don't need to understand a whole lot to understand the basic 'mechanics'. You just need a really good reference for the actual instructions.

First, realize what a CPU actually does. Realize what machine code does. Learn the parts of the CPU (roughly speaking) - instructions, pointers, registers, flags, etc. Learn some basic EE concepts such as what "high" and "low" mean, and what a "line" is, for example. It's a prerequisite to reading some of the meatier bits of documentation.

Secondly, reading the CPU guides for whatever ISA (Google "AMD programmer manual volume 3" for x86_64 platforms for example) is a great start. They're full of useful information, and AMD's in particular is very easy to read, albeit large. Skim through it, especially the first bits that explain what the registers are.

Then use NASM to write a simple program that exits 42. Get there first. Learn what the different directives mean (e.g. `.text` for ELF output).

Then start to add instructions and play with registers. Learn about calling conventions. Write some C code and emit S files (google it) to see how it compiles down to machine code (turn of optimizations when you're starting out).

Get familiar with Godbolt.org, it'll help with the last thing on that list.

Any book is going to help, though pay attention to the syntax it uses (avoid GAS syntax, in my opinion) and the platform it targets (make sure you have access to that platform, e.g. don't pick up an ARM book if you're on x86). It'll make things very hard to follow if you don't.

These are just tips, but maybe they help just a bit.


Why would it stress you out?

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.


>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.

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).


Like other posters said, don’t sweat learning it early, just do the assignments.

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/


I think the idea of a course is that you will be taught. Why worry about it? Do you not trust your uni to provide the necessary course materials and exercises?

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.


> Did someone tell you assembly is hard? I will tell you that assembly is easy, very easy.

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.


> I like assembly, but the idea that assembly is easy is not realistic.

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.


> a handful of instructions are needed for turing completeness and you can ignore most of the rest.

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.


Well, doing something that the platform or language doesn't help you with or isn't designed for can be hard (or impossible), but I think that is true of literally any and every system.

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.


I think assembly has an undeserved reputation for being difficult

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.


Once it "clicks" it's actually easier than most high-level programming languages IMHO ("easy" doesn't necessarily mean "productive" of course). Some CPUs and assembly dialects are worse than others though (e.g. x86 was never "enjoyable" for me).


My first experience was in my teens, using a disassembler to change hardcoded keybindings in a game (x86) and then defeat some kind of checksum (anti-tamper?) mechanism because otherwise it wouldn't run after the modifications.

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 think the idea of a course is that you will be taught."

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


Some things that were high value to me,

1. Play through the first page of levels of TIS-100. This is a game you can buy on Steam. After spending a few hours working on problems in this, I felt a hard-to-describe mental shift that removed the intimidation of assembly.

2. Work through the first half of /Programming Boot Sector Games/ by Toledo.

3. Designing and building a simple instruction architecture, implementing it as a VM, writing an assembler for it.

The ChibiAkamus tutorials on youtube may be worth a look, also.

If you try for TIS-100, give yourself a decent chance to get into it. Print out the manual, calmly read through it with a biro, don't let yourself give up easily on the first few problems.


I would recommend another Zachtronics game, EXAPUNKS. You write assembly in that game too.


Absolutely, assembly got much easier for me after playing this.


Thank you for the book recommendation.

About TIS-100, while I had never played it, I've played some Shenzhen IO.


Isn't TASM "turbo assembler" ? that is 16/32 bit. What I would do is to get hold of someone from previous year and ask about the classes. If it is turbo assembler than figure out how it is setup. If it is vm etc... and once You know this you can pick probably a book that fits.

When 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.


I think that we're supposed to use DOSBox for that. I've managed to get that running, though now I have issues understanding how DOSBox works.


8bitworkshop is great:

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).


Speaking as someone who has spent probably 10 years writing assembler:

Assembler was difficult in the old days because you would load your code, and it would crash, giving no information on what went wrong. These days you can run stuff in a simulator that will print out what changed at every tick. Yes, your attempts will crash a lot and it will take you a long time to write a program that hardly does anything, but that will be true of all the people on the course.


I don't know if I'm the right guy to answer this, but I've written a lot of assembly on the side as part of VM and emulation projects. I think the first time I really understood how simple some things can be was when I wrote a simple function that did nothing but returned back to the caller.

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:

    int main() {
        extern void my_assembly_function();
        my_assembly_function();
    }
Now you have to create your assembly file, and then compile it to an object file that can be linked with your program:

    gcc -c myassembly.S -o myassembly.o
OR

    nasm -f elf64 myassembly.asm -o myassembly.o
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?


> Is this programming on Windows or Linux?

Considering that it's TASM it's good old DOS.


If a "modern" high level language is like a shop with machines full of safety features and refinements, lower-level languages are similar but the bandsaw won't try to stop before cutting your fingers off, and assembly is like building by hand (some platforms might give you an electric drill and 50 different saws, others, just a chisel). In many ways, it's easier to think about, but it also lacks the easy guide-rails and labor-saving machinery that make high level attractive.

Assembly will give you the context to really appreciate why higher-level languages work how they do, especially the older ones like C.


I highly recommend starting with the amazing book "Assembly Language: Step-By-Step by Jeff Duntemann" It's 90% about architecture and 10% about actual syntax/coding. Covers both TASM/MASM. There's a few different editions - the earlier ones include DOS specific info.

It's the type of book you can almost read in one sitting. It's that enjoyable.

It's basically the absolute best "beginners" book. Read this first, THEN get into a proper assembly book (that can be more of a reference to the instructions, etc).


What's your background? Obviously, if you're studying marketing or sociology, learning computer assembly is going to be a challenge.

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'm studying "informatyka stosowana" (Software Engineering would be the closest thing to this, I guess)

I have background in both C and C++


The transition from C to assembler is a relatively minor step. What you'll notice is that there's a pretty good 1:1 translation from every C statement into assembly, so if you already have the mental model to grok C (control flow, function calls and pointer arithmetic), learning assembly won't introduce many new concepts. Instead, it will provide a better grounding for everything you (think you) already know from 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.



I read this to get up to speed when I needed to take my school's Operating Systems course before the Assembly prerequisite, and it got me through ok with a little help from my lab partners.


I think TASM, isn't that difficult. I remember learning this in a university course and I actually quite enjoyed it. There are youtube videos out there.

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


My Uni had this weird notion of teaching assembly with made up processors. It was some professor's hobby to write emulators with a semi-graphical environment that showed the registers, and so on.

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.


When I took the compiler course in university around 2004/05 we were using some Motorola CPU iirc, definitely old but real.

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.


I have dabbled with quite a few assembly languages (8051, MIPS, A64 and a bit of x86), the first and second of which I learned in school. To be honest if your teacher is good and the class is well prepared, it should be pretty nice ! As fmax says in their comment it's not that different than learning any other new language : there are some key concepts and ideas which you'll need and the mnemonics, which are the assembly keywords like `ADD` (better to have a searchable reference handy). But all those things can be acquired by experimenting with it and writing simple programs. On top of that, you say the course is on computer architecture so I bet you'll have a very useful overview of all those concepts that are useful for assembly writing ! peterkelly's link looks very useful for that purpose as well.

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/


I've played a bit of Shenzhen IO. I quite liked it, but I haven't had mental patience to go very far with that :D

Thank you too


https://www.youtube.com/c/BenEater

This is a very good channel that will help you. He goes through assembly language in various videos as part of demonstrating different topics and I'm not gonna lie but he make it seem very simple and obvious.


I agree with the bulk of posters who are advising you to stop stressing and that the course has taught thousands of students before you who didn't specifically prepare for it.

What I'd probably do instead is to take a language like C and learn how the compiler translates C to assembly with optimizations turned off and targeting a simple processor (maybe an MSP430 or an AVR). If you already know C, this exercise will teach you why I consider C to be "portable assembly language".

Or, you could enjoy the time between now and then doing whatever you like and show up to the course well-rested and ready to learn. It's hard/expensive to make large, complex programs in assembly. It's not hard to learn the essentials of it for a computer architecture course purposes.


A little outside what you asked but https://www.nand2tetris.org/ is a good introduction to computer architecture and assembly.

For something a little more complex you could have a look at a 68000 course https://www.youtube.com/watch?v=UpNS-IVsBew&list=PL-i3KPjyWo...


Don't stress on assembler. This should be a fun class for you. If they are using TASM then it's early x86, so not the funnest (like 68000 or 6809), but not especially hard.

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.


Go download Exapunks, Shenzhen IO, and TIS-100. I didn’t have that option when I was in your position, so I read Intel’s pentium programming manual and made a Winamp viz plugin instead.


A practical approach is sometimes useful. Write a simple "Hello World" in C and compile it with full debug symbols. Then open it in GDB and step through. Or alternatively, open it in Ghidra and follow the instructions to see how they map to higher-level code. Try the same on increasingly complex programs. Try the same with C++ instead of C, or Rust to see how different languages produce different ASM. Try compiling to ARM versus X86 to observe the differences in architectures.



If you already know C or C++, I’d recommend checking out Compiler Explorer [1]. It helped me tremendously when learning assembly as I could see how source code translated to assembly, which helped me learn common patterns in assembly, etc.

[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.


I recommend"Programming from the Ground Up"

https://www.google.com/url?sa=t&source=web&rct=j&url=https:/...



Any decent book or course on programming microcontrollers. Ideally, if you can get a cheap microcontroller test board, you can quickly see and appreciate what your instructions do. That said, using assembly in a PC is quite a different abstraction and it depends realistically how much you will use it on your course.

If it is just a module, I wouldn't worry too much about it and just look at the college's recommendations.


I would be sooo excited if I were you. I don't know if you're the type of person who likes to break stuff and figure out inner workings of programs. But the moment I fell in love with assembler was, when I was able to DISassemble a program and understand it bit by bit. Read process memory from another process, inject and modify code. IDK to me it was the first moment I felt 'in control' :)


I think I learned more from Ben Eater’s “Building an 8-bit breadboard computer” series [0] than my intro to computer architecture course at university. Highly recommended.

[0] https://www.youtube.com/watch?v=HyznrdDSSGM&list=PLowKtXNTBy...


The basics of assembly aren't bad, but there's a lot of bad tutorials out there. Look for the ones that start by explaining what a processor register is.

https://www.cs.virginia.edu/~evans/cs216/guides/x86.html



I can’t speak for TASM, but I learned 6502 ASM for my senior project. It can be daunting, and for me the trickiest part was reducing down to what I wanted to do. I suspect it’s more complicated for larger addresses and more features, but still it’s ANDing, ORing, and simple math. You’ll get it.


I wrote a guide that may help -- it enables gdb debugging within consistent containerised environment: https://blog.devgenius.io/getting-started-writing-assembly-l...


I've never heard of prepping for a university course - the whole point of taking the course is to learn.


Competitive students I knew regularly prepared for university courses in advance. In their view, the whole point of taking the course is not to learn, but to optimize their study/game the system enough to earn as high marks as possible for professional opportunities in the future. As they were both hard workers and optimized for marks, their tactics generally worked for their goals.

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.


I just learnt assembly last week, and I made a list of all the resources I used:

https://loughton.me.uk/2022/01/01/assembly-language.html


I liked this book for TASM. However, it's pretty much outdated now

https://www.amazon.com/Mastering-Turbo-Assembler-Tom-Swan/dp...


It's quite the luxury to be at a University, with knowledgeable professors at your fingertips. Ask them for help if you get stuck and can't do a web search to find what you need. Classmates can be helpful too if you think they have some competence.


Have a look at this: https://hackaday.io/course/178733-raspberry-pi-pico-and-rp20...

His youtube videos are interesting as well.


40HEX and 29a computer virus ezines. I can also recommend Ralf Browns Interrupt List for a great reference for BIOS/DOS interrupts (procedures).

Definitely not along the lines of what you're going to be taught, but fun.


I highly recommend Assembly Language and Computer Architecture using C++ and Java by Anthony Dos Reis. This book will teach you a lot of stuff in assembler.


It gets posted every so often here but:

https://asmtutor.com/

Is a good intro to writing x86_64.


Why not MIX? Find an old edition of Fundamental Algorithms




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

Search: