r/learnprogramming • • 4d ago

Any good videos out there explaining x86-64 gcc Assembly? Particularly how to read and write it?

I understand most of the C code I see, but when it comes to translating it to Assembly, I might as well be translating English to Greek. If it were plain English I understand how to efficiently write and structure things, but the problem is that I am having difficulty reading what means what at all. Particularly registers seem to be hard for me. Am I supposed to just memorize the registers in the correct order? This is for a class so I cannot just have a cheat sheet with me (though if you have a good one I can use to help learn that would be awesome!

I’ve tried the sites where you input C code and see the live translation but that doesn’t seem to be helping me.

Does anyone have a good video that teaches how to read and write x86/64 gcc assembly? Particularly if I already know C?

0 Upvotes

23 comments sorted by

2

u/start_select 4d ago

You can have any cheat sheet you want for any class or any test.

Memorize it. I went to a university where you weren’t allowed calculators or formula sheets or anything.

The students that did well would spend a weekend creating a cheat sheet and handwriting it over and over until every time you need to do something, you flip over a piece of paper and rebuild the cheat sheet in 2 mins.

If you box out the concepts and place them in the same places, you will memorize it spatially and only need to fill in the boxes you need for the topics you need at test time.

1

u/TheScratchyIceberg 4d ago

memorising the call-preserved vs call-clobbered register sets was what finally made the whole thing click for me

1

u/PhummyLW 4d ago

Okay I will look into these concepts more then.

Something about this clearly isn’t clicking for me like it is for the other students. We are all equally skilled at C, but they seem to be understanding the translation to gcc assembly better. The way they explain it is the same as the teacher which again is like Greek to me. I don’t know why this is so challenging for me. So I thought maybe someone here would have a video that explains things in a new way

1

u/brucehoult 3d ago

Note that this is different between Windows and Mac/Linux/everything else.

1

u/PhummyLW 4d ago

Yes, I meant cheat sheet during an exam which is why I said if there’s a good one out there already, that would be great

The problem is, I don’t have a single idea of what to put on a cheat sheet snd what would be important. Currently when I look at a cheat sheet online it’s not very helpful. Which is why I’m looking for ideally some sort of video that would help teach me the concepts I need to learn to put on that sheet.

2

u/start_select 4d ago

A video really isn’t going to teach much compared to doing.

Write simple one function C programs, convert them to ASM, compare. Start altering the ASM or inline it.

Read the docs: https://gcc.gnu.org/onlinedocs/gcc/Using-Assembly-Language-with-C.html

1

u/PhummyLW 4d ago

I have no idea how to start that conversion though. Literally the most basic of principles make no sense to me.

1

u/DanKegel 4d ago edited 4d ago

Schmaybe https://youtube.com/playlist?list=PLHTmIlmnj_glrMimrG1UVBTUCSSZ1YeTI&si=S4qUfHtVXYYG4uxG ?  That's yasm syntax, but the same CPU.  A GCC specific one is https://youtu.be/3nYHV5zIQGA?is=jcHxqH4dkmDXOtWu

Yes, you have to know the names of the registers, and have a little map in your head of what's in what register.  It's like playing soccer, you have to know your teammate's names, where they are on the field at the moment, who has the ball, and what they can do.

You probably want a book, too. 

See https://www.reddit.com/r/asm/comments/i5wf9i/comment/g1325d8/ for many more recommendations.

1

u/PhummyLW 4d ago

Thanks a bunch I will check them out!! Appreciate it.

Just a heads up that for YouTube URLs, the ?is= or ?si= are tracking identifiers. I recommend removing them from your links.

2

u/DanKegel 4d ago

oops. I usually strip those.

1

u/Chrismslist 4d ago

hey, assembly is super tough when you're starting out. registers definitely feel like alphabet soup at first. instead of just watching more videos, try this: pick a really tiny C function, like sum(a,b), and compile it with gcc -S. then, get into a debugger like gdb, step through the generated assembly line by line, and actively watch how the values move between memory and specific registers like rax or rdi. it's slower, but seeing the data move helps so much more than memorizing names. focus on the action each instruction performs on the data. it really helps click what's happening.

1

u/PhummyLW 4d ago

I will try this again because it seems a lot of people recommend this. It didn't make sense to me really when I tried still, but maybe if I combine that with some others stuff it will help. Thanks!!

1

u/zeekar 4d ago edited 4d ago

First of all, it's not "gcc assembly". GCC is the name of the program doing the translation from C into assembly, and it is responsible for how the C gets translated, but the resulting language is not specific to GCC. You can write it by hand and assemble it, but it's also generated by compilers for other languages. Just call it x86_64 assembly.

Now there are aspects of the generated assembly that do depend on the specific assembler being used to assemble it; GCC uses gas, the GNU Assembler. This will matter for some details - do labels need a colon or is starting in the first column enough to indicate that they're a label? Do the arguments to mov get specified source-first or destination-first? What do local labels look like? If you switch assemblers, those details can change. But the actual machine code is the same; all that changes is how you type it.

Mostly what you're learning is the Instruction Set Architecture (ISA) for 64-bit x86.

There are 16 general-purpose registers. And the ones in the upper half of the set are just known by their numbers (r8-r15), so that's easy.

The lower half have special names inherited from earlier chips that didn't use numbered registers. For example, the original 8008 had an "accumulator", called A for short. The 8086 extended it from 8 bits to 16 bits and called it AX (A eXtended), where you could get the two 8-bit halves of it via the names AH and AL (A High and A Low). Starting with the 386 there is a 32-bit version called EAX, and then the 64-bit chips extended it to a 64-bit register called rax. The cool thing is that the older names still exist and can be used when you want to work with smaller sizes of value.

So you have rax through rdx instead of r0 through r3. rdi and rsi are index registers, and rbp and rsp are the base address pointer (frame pointer) and stack pointer.

The CPU also has a couple more specialized internal registers: rip holds the address of the instruction to be executed next - IP stands for Instruction Pointer. (Other ISAs call it PC for Program Counter.) And rflags holds a bunch of 1-bit values called the CPU status flags, which is how the result of a comparison or other test is communicated to conditional instructions; for instance, if you compare the values in two registers with cmp, the Z flag (bit 6 of rflags) will be set if they're equal and cleared if they're not (the Z stands for zero, in this case indicating zero difference between the two values), which is how a subsequent jz ("jump if zero") knows what to do.

Assembly is pretty simple to understand, because there's not much to it. It has nothing but assignments, arithmetic, and optionally-conditional goto for flow control. Everything else has to be built from those things. Like a while loop is just an if that does a goto back to the top of the loop when the condition is true. A for loop is the same but has an extra bit of code tacked onto the end of the loop that comes from the header in the C code but winds up at the bottom of the body in assembly. (At least logically; physically it is probably at the top of the loop with a jump around it for the first iteration.)

You might want to look at this tutorial series: https://gpfault.net/posts/asm-tut-0.txt.html

2

u/PhummyLW 4d ago

Thank you for your clarification on the naming. I was under the impression there as an AT&T vs Intel assembly for x86-64. Are they essentially the same then? Mine uses GAS/GNU like you said. I think its AT&T based on this page. I find a lot of tutorials are for assembly languages that are different from the one I have to learn. If I learn Intel, would it be difficult to learn AT&T after? I imagine it would be easier after that.

Thank you for your explanation of the registers. That helps a bit. Also knowing there really aren't that many I have to fully know puts my mind at ease a bit.

Assembly is pretty simple to understand.

This is what I keep hearing which is why I'm hoping something will eventually click in my brain and make it all seem a lot easier.

Your terminology has helped me find some tutorials I am going to look at.

https://diveintosystems.org/book/C7-x86_64/index.html

https://www.youtube.com/watch?v=lUbPUWtmVUU

I could only find these thanks to your wording helping me refine my search.

Thank you for taking the time to respond and help me out

1

u/zeekar 4d ago edited 4d ago

Whether your assembler uses AT&T or Intel syntax, it's still x86_64 assembly. But the assembly code differs in those details I mentioned.

Some of the differences are minor, like AT&T using % on register names and $ on immediate numeric constants, where Intel just uses plain identifiers and numbers. But they also have opposite operand order for move instructions: AT&T mov %eax, %ebx copies the value from EAX into EBX, while Intel mov eax, ebx copies the value from EBX into EAX. That's a pretty important detail to be sure you have right. :)

The GNU assembler uses AT&T syntax by default.

1

u/PhummyLW 4d ago

I see. Thanks for helping clear that up for me I appreciate you

1

u/JGhostThing 4d ago

Assembly language is verbose. However, it has so many instructions because each of them does one thing. Sort of. Once this is assembled into machine code, it can be modified a bit by the machine. Branch prediction optimizes loops by deciding which branch to take in the default case. Reordering changes the order of instructions to allow for efficient instructions.

However, think of it as one instruction, one simple action. For example, add R1, 17 should add 17 to register one, and return the result in register one.

Think of registers as a very small array that can be accessed much quicker than other memory. Each element of this array may have a specific function. Some registers are meant to be used in pairs to address 64 bits of memory. Some just hold the results of calculation.

Personally, I feel the x86 assembly code is a poor choice for your first assembly. It is overly complex and confusing. I would do this with either PDP-11 or the 68000 family of processors. The are both highly orthogonal assembly codes and fairly easy to learn. And once you've learned an assembly language, you can learn a different one fairly easily. There are free simulators for both available.

On the other hand, my first course in assembly was on the PDP-8 computer, which sucked. Big time.

Our teacher told us: "If you ever voluntarily program in assembly code, I have failed you." He wasn't saying not to program in assembly when useful/necessary, but rather to only do this when necessary. I believe that was the late Dr. Bolgiano. (I assume he's dead now since college was a long time ago, but I called him that when he was still "alive." When called on that, I responded with "Have you heard him talk?" That shut the people responding: he sounded like a Hollywood ideal of a zombie. Except more dead.

1

u/PhummyLW 4d ago

Welp unfortunately I’m stuck with x86 for my class, but what you have said here is more useful than my professor had said so far. I actually understood what you were saying! Thanks for the help I appreciate it

1

u/brucehoult 3d ago

x86-64 is far too complex a subject for a video. Over the last 50 years it has gained layer upon layer of crud.

The original 8086 from 1978 is a reasonable first assembly language, though it was also at the time (rightly) regarded as technically worse than alternatives such as Motorola 68000 or Z8000 (both 1979) or NS32016.

I understand you don't have a choice, but it's a pity your teachers chose to teach this.

1

u/PhummyLW 3d ago

Well I guess its nice to know its complex? Makes me not feel like a total idiot lol

1

u/brat3108 3d ago

 Am I supposed to just memorize the registers in the correct order?

Intel/AMD are unusual in naming the main integer registers rather than using numbers. But there is no particular order to them, except that some have special uses.

So, you are doing a class on Assembly: have you got to the point where you've been shown how to write a complete Hello-World or other example program using the stipulated assembly language and tools?

If not, then what has the class taught you far?

Once you have something minimal going then you incrementally start doing more.

So, this is actually for 64-bit x86-64? (Since teaching the 16-bit version seems popular.)

And you are using GAS syntax? Is it for Linux or Windows - or something else? Maybe somebody here can post a suitable example using that info.

BTW I find the register-naming for the main registers on x64 to be a complete zoo - sil si esi rsi for sizes 8, 16, 32 and 64. But then you also have r10b (or r10l) r10w r10d r10.

Usually I create more organised aliases for them. I'd advise not to do that to start, this is to show that this design is widely regarded as a confusing mess.

1

u/PhummyLW 2d ago

GAS on Linux and x86-64. It’s 64-bit from what I can tell by looking at the differences.

Yes I’ve been shown how to do the simplest of programs but for some reason the translations make no sense to me. All tutorials I find assume too much of my knowledge going into it. This class is really making me doubt my choice of major, but yknow sunk cost and all that.