x86-64 Assembly For Loops Explained – YASM Tutorial

x86-64 Assembly For Loops Explained – YASM Tutorial

Quick practical guide showing how to implement a classic for loop (i=0; i<n; i++) in x86-64 assembly with YASM. We break the for loop into init/check/update parts, convert it to while-style logic, then build it with compares, conditional jumps, inc, and unconditional jumps back to the top. Includes real working code, user input, and printed output.

Great for students learning assembly after C/C++, OSdev hobbyists, or reverse engineering beginners.

Introduction to For Loops in Assembly 00:00:00
For Loop Structure in High-Level Languages 00:00:28
Breaking Down For Loop Parts: Init, Check, Update 00:01:04
Converting For Loop to While Loop 00:01:52
Why While Loop Style Helps in Assembly 00:03:16
Program Overview and Setup 00:04:12
Data Section – Strings and Messages 00:04:40
External Functions and Hybrid Program 00:06:11
Entry Point – Looper Function 00:07:12
For Test Function and Register Usage 00:07:42
Preserving Callee-Saved Registers 00:08:05
Printing Welcome Message 00:09:00
Prompting User for Number 00:09:48
Getting User Input 00:10:25
For Loop Structure in Assembly – Comments 00:11:12
Initialization – Setting Counter to Zero 00:12:50
Loop Top Label and Condition Check 00:14:28
Conditional Jump Setup (jl) 00:15:07
Handling Jump Distances 00:15:34
Loop Body – Printing Current Number 00:16:58
Update Part – Increment Counter 00:18:40
Unconditional Jump Back to Loop Top 00:19:14
Loop Done Label and Exit 00:19:55
Printing Goodbye Message 00:20:23
Testing the Program 00:22:08
Final Results and Demo 00:22:24
Outro and Call to Action 00:23:25
Thanks and Subscribe Request 00:23:45
Website and QR Code Mention 00:24:38
Closing Thanks 00:25:16

=-=-=-=-=-=-=-=-=

Thanks for watching!

Find us on other social media here:

  • https://www.NeuralLantern.com/social
  • Twitter / X: https://x.com/NeuralLantern
  • Rumble: https://rumble.com/c/c-3696939
  • BitChute: https://www.bitchute.com/channel/pg1Pvv5dN4Gt
  • Daily Motion: https://www.dailymotion.com/neurallantern
  • Minds: https://www.minds.com/neurallantern/
  • Odysee: https://odysee.com/@NeuralLantern:5

Please show your support!

  • Buy me a coffee: https://ko-fi.com/neurallantern
  • Subscribe + Sharing on Social Media
  • Leave a comment or suggestion
  • Subscribe to Blog: https://www.NeuralLantern.com
  • Watching the main “pinned” video of this channel for offers and extras

Hey there! In this video I’m going to teach you how to implement for loops in YASM x86-64 assembly.

Although if you’re using a different type of machine or a different assembler,

this video should still be useful to you because it’s mostly about the concepts involved in implementing a for loop.

Okay, so for starters here, what am I even talking about? Let’s do…

are you even talking about dude imagine in a higher level language we have a for loop here

and so we have like four size type i equals zero i is less than 99 i plus plus right probably most

programmers looking up assembly uh on the internet probably are interested in uh or probably already

know how to implement for loops in c plus plus so let’s just pretend that you do and so inside of

your for loop we’ll do stuff and what happens here is uh well you know this for loop is going to run

Well, you know, this for loop is going to run 99 times.

It’s going to start at zero.

And, you know, so we have like an initialization part right here.

Maybe I should copy paste this and kind of break down the parts.

We have an init part here for the for loop.

We’ll say init part.

And then here we have a check part.

We’ll continue to loop as long as this expression is true.

You can make a big complicated expression if you want to,

but we’ll just keep it simple for this video.

So I’ll call this the check part.

And then we have sort of an update or a maintenance part.

an update or a maintenance part. So I’m going to call this the update part where we increment our

counter variable, move pointers, even call functions, do whatever it is you think you need

to do to update the loop so that it runs it, you know, so that the loops don’t actually have to be

integers. But in this case, I think it’s better, it’s easier to understand what the loop is doing

if we just kind of break down these parts. Anyway, so what is really a while loop? Sorry,

but a while loop that breaks and has break has like a nit logic and breaking logic and checking logic just in specific places.

Imagine this. What if I said before the loop starts, I’ll let’s let’s say we’re going to do a while loop before the loop starts.

I’m going to initialize a variable size type I equals zero, right?

That’s the initialization part that’ll only happen one time.

And then when you have a while loop and it checks to see if it should keep going, that’s

the check part of the for loop.

So I’ll just say while i is less than 99.

And then for the update part, we just have to stick that inside of the while loop somewhere.

Depending on your logic, you might want to put it at the top or the middle or the bottom.

I’m going to put it at the bottom because I’m going to expect that it happens right

before we do the next check.

So I’m going to maybe do a comment here and call it the update part and I’m just going

So maybe if I update this code to print something, it’ll seem a little bit more clear.

Value of I is, and then I’ll just say I end L, and then I’ll copy paste that to here.

And then I can also put this inside of the while loop.

And now we have transformed our for loop into a while loop.

transform your for loop into a while loop it’s pretty easy to implement in assembly if you

already know how to implement while loops so i should again say that there are lots of parts

i don’t know if i said that during this video but there are lots of things in this video that i’m

not going to that i’m not going to explain specifically because i’ve already explained

them in other videos so for example implementing a while loop is in another video so if you don’t

already know how to implement while loops if you don’t know how to use conditional branching or

If you don’t know the basics of assembly, hybrid programs, make files, all the basic stuff that I’m going to skim over in this video,

then you should probably check out my other videos first.

But for now, I’m just going to assume that you know how to implement a while loop.

And really the lesson is, hey, just take your for loop and convert it into a while loop.

And then you can implement the while loop pretty easily.

That’s the secret as far as I’m concerned.

So imagine this now. Let’s do some assembly code.

I have a source code file here called looper.asm for assembly.

And you can imagine that I have a hybrid program running under the hood.

I’m not going to show you all the code involved.

I’m not going to show you the make file or the C++ driver that calls on this module.

We’re just going to write the assembly here.

So, you know, if you’re writing pure assembly at home to practice, that’s fine.

Just keep in mind, there’s like a few things under the hood that I’m not showing in this specific video.

So first off, I’m going to copy paste my data section.

paste my data section of my assembly program. The first thing to note is we have a bunch of

C strings here. We’re basically going to be telling the user, hey, we’re going to begin

the four tests. Maybe I should have capitalized for, I’ll leave it. And then we’re going to prompt

the user for a number. We’re going to say, please enter a number. The loop will print from zero to

the number minus one, which is like the typical four loop that you usually write in the most

and then we’re going to have a little prefix we’re going to say you know like an arrow and then we’re

going to print the number back to the user that we’re looping through so if the user enters a

10 it’s going to print the arrow 0 and then arrow 1 arrow 2 all the way up to arrow 9

and then when we’re done we’re going to print an ending message so this is nothing new if you know

assembly already just c strings that will print with system calls see my other videos if you don’t

And then a CRLF string, just basically doing a new line, a carriage return new line feed

on the system.

And then we’re going to output using system call code one.

And we’re going to use file descriptor one so we can print to standard output.

Okay.

So now the real fun begins.

Let’s start our text section, which is where the instructions of our assembly program go.

So I’m going to do text section, section text right there.

And I’m going to use two external functions to just help me input and output numbers to the user.

If you wanted to, you could use a system call that just inputted a character.

And then you could just kind of like loop printing various characters.

And like, let’s say if the user typed A, maybe you could imagine doing a loop that increases the character that they typed all the way until it hits Z.

Or if they hit, you know, F, it’ll just print F all the way to Z.

to z you could do that without using an external library for printing integers this video is not

about this library right here so i’m not really going to go over it but uh you know you could

hard code the start and end points when you’re practicing um you could you could use a different

library or a different function call to get the inputs you could use a system call just to input

one character um or you could you know use a hybrid program to to utilize printf and scanf

f. Either way I’m just going to be using these two functions just to like get input and output.

It’s not really part of the idea of looping. So now let’s start our entry point.

Our function is called looper. Since this is a hybrid program you can imagine there’s a C++

module elsewhere calling on the looper function and so that’s why I mark it as global so it can

be called upon. And then I have another function called for test. I don’t really know why I chose

it this way but i wanted to make another function that was called upon by our entry point here

so the looper function really doesn’t do anything except recall the for test function

so now let’s start the for test function actually maybe this is where the fun begins

so i’m gonna put it down here and so you can see the signature it doesn’t take any arguments it

doesn’t return anything it just does stuff and then i have a note to myself this is how we’re

going to use the registers we’re going to use r12 for the user’s number and then we’re going to use

And then we’re going to use R13 to keep track of where we’re going.

So let’s see.

I’m going to start by saying let’s preserve R12 and R13

because you have to respect the application binary interface, the ABI,

and that designates R12 and R13 as Kali saved registers.

If I don’t preserve those and my program is even a little bit complicated,

I’m probably going to be debugging forever

debugging forever or I’m going to just crash my program for no reason. So I’m going to just

do a push pop pair. Notice how the pops are in reverse order. This is not a push pop video,

but just so you know, I guess while I’m here, I’m going to copy paste my crlf function,

which really does nothing. It just prints out the crlf string with a system call. That’s all

Okay, so do I even need CRLF in this program?

I think I just modified this.

Maybe I don’t even need it anymore.

No, I guess I do.

The first thing we’ll do is we’ll print an introduction message to the user.

So inside of the for test, we’ll just use a system call to print out, you know, a welcome

message to the user.

And then I’m going to call CRLF, which will just give us a new line.

And yeah, you can hard code, you know, the 13, 10 at the end of these strings, but I

don’t really like doing that.

doing that. Okay, so we should have a working program at this point. Let me see if it actually

does work. Clear and make run. Okay, so the driver prints a little welcome message. You don’t see the

driver code, but that’s what it’s doing. And then the for test prints the welcome message that we

just added. And then the driver lets us know it’s retained control. And then it’s responsible for

returning to the operating system for us. Okay, so then the next thing we’re going to do is we’re

we’re going to ask the user for a number so that we know how many times to loop.

And again, you could hard code this number if you don’t want to do IO right now.

You could even print a character a certain number of times

if you don’t want to even deal with printing an integer.

But I’m going to ask the user for a number.

That’s going to be the prompt string.

And if we run it again, now you should see it asks the user for a number.

So it’s going to say, please enter a number.

The loop will print from zero to N minus one.

print from 0 to n minus 1. It doesn’t actually ask for the number though. It doesn’t actually

I guess take the number so that’s going to be my external library that this video is not about

where I just call a function called input assigned 64 integer and I’m going to receive that back in

rax and I’m just going to save rax into r12. So r12 is now going to be the number that the user

inputted and that’s why up here I have it designated as the user’s number. So really not a big deal but

a big deal but uh you know if we run it again it’ll ask for a number and then it won’t do

anything else it’ll just kind of quit okay so now we can implement our for loop this is going to be

a little tricky so we’re going to start off with the initialization part remember we had several

parts here if i just kind of drag this off to the side maybe pin it up to the top so we can see it

aren’t we? If I move it a little bit to the side. So remember that for loop, it’s got an init part

and a check part and an update part. And I’ve kind of added that as a comment just to remind myself

of the way my mind is supposed to be wrapped around this concept. And so I made another comment

here with four and then empty parentheses just to denote that some comments that come below

I guess the top of the for loop

So now I’m going to make a label here and what I like to do with my labels is I like to

prefix them with the name of the function that I’m currently in and then an underscore and that kind of helps me keep track of

My symbols a little bit more easily, especially if I have a large module the symbols are less likely to overlap if I prefix them with the

The function names

to be Fortest underscore something and since I’m only doing one thing inside of the Fortest function

I’m just going to have a suffix only for the most part but you can imagine if you had more

parts inside of your function and it started getting a little cluttered you might want to have

you know another label you know that just sort of another I guess like part to your label that names

the part of your function you’re in although this is assembly it gets really hard really fast so

really hard really fast so if your function is even a little bit complicated you should probably

consider breaking it up into multiple functions if you can. We can’t really do that at this point

because it’s just a for loop but keep that in mind. Okay so we’re going to initialize. Remember

the first thing we had to do to initialize was you know setting i to zero or you know whatever

it is that we’re going to set up in the init part so I’m just going to do that here. I’m going to say

That’s the first part, the update part where we set size type i equals zero.

In fact, maybe I could do another copy paste of this.

Where instead of using a size type, we’ll just say that the register r13 equals zero.

I know that’s not going to make sense in a higher level language right now,

but just so that the for loop looks a little bit more like assembly.

We’ll keep going as long as r13 is less than r12.

and then we increase R13.

So I’m just going to put ink R13

so it looks more assembly-like,

even though this completely and totally

would not compile in C++.

I hope that this helps your understanding a little bit.

So yeah, we can do everything

except for just the increase part at the very top.

I’m going to choose to increase it at the bottom.

If you wanted to, I guess you could start off R13

as a negative number and then increase it at the top.

But I personally don’t feel that’s like very clean.

feel that’s like very clean it also forces you to use signed integers maybe you wanted to use an

unsigned integer so you could get like a gigantic um maximum number that you looped up to i don’t

know so we’ll just initialize here and we’ll say r13 is equal to zero the init part should not be

part of the actual like looping like every time you loop up to the top of the for loop you should

not repeat that part again it should only happen once so the next label that i have is called loop

have is called loop top and that’s just going to be the top of the loop that I

continue to go back up to every time I want to see if we’re supposed to

continue looping and then go into the loops body so maybe I should say that’s

why this is named to underscore loop top and I don’t know you don’t have to do

camel casing and your labels you know you could just do loop in it or whatever

but I’m just choosing to do it this way so at the top of our loop we’ll be

Remember that was the check part, right?

So we’re going to check to see that R13 is still less than R12.

If it is, we’ll continue with the for loop.

If it’s not, then we jump out of the for loop.

So that means probably the true case where R13 is indeed less than R12,

that’s going to be a short jump just into the loop’s body.

And the false case where R13 is not less than R12,

that should probably end up being a much longer jump.

on how big your your loop is maybe that jump is too long too far away for a conditional branching

instruction to reach if you’ve watched my previous videos you should know already that

the conditional branching instructions like jl like jump less than they can only reach about 128

bytes away if you try to go further than that the assembler will actually stop and block you from

finishing your compilation it’ll say i think it’s like jump out of range or something like that

So you want to try to keep the short jump points with your conditional branches.

And then in the false case, where the conditional branch doesn’t actually do anything,

then it falls through to the next instruction where you will have an unconditional jump.

And remember, the unconditional jumps, they don’t have a limitation of 128 bytes.

They can jump like all over the place.

Like they can jump anywhere, basically.

that means if you think about it, we come in to the loop top right here.

We immediately do a compare instruction and a conditional branch.

So if R13 is less than R12, meaning we should continue to for loop,

then we’ll just do a short jump into the loop’s body and actually execute its body.

And if not, we will end up falling through to line 92,

where there’s just an unconditional jump instruction that just says,

all right, let’s jump all the way down to being done.

Let’s jump all the way down to being done, which could be very far away for all we know.

Okay, so we’ve done that.

Now let’s implement the loops body because the first thing that we did is we wanted to

jump into the loop body to actually execute our instructions, which in this case, we’ll

just be, you know, printing a number every time we loop and then increasing that number.

So I’m going to do a little like new line there.

I’m going to paste the loop body.

little comments to help remind myself that this is actually the loop’s body. So for test loop body

that takes care of the branching instruction, hitting on that and actually going into the body.

And then later we’re going to have to implement a label for the loop being done. But for now,

we’ll just say the body. What does it do? It just prints a little message to the user.

If you look at the message for current number string, if I go up real fast,

message for current number, it’s just an arrow. So the user’s going to see an arrow and then

So the user is going to see an arrow and then their current number, I guess of the loop’s

current number.

And then every time it loops, it’s just going to continue printing that arrow with a number

on it.

So we’re doing that.

And then we’re going to say R13, which is the current counter variable, which started

at zero is going to get loaded into RDI, which if you watched my other videos, it’s just

the first integer argument for a function call.

So I’m just going to call this other function here, which is not part of the video to just

which is not part of the video to just say hey please print this number for me so the first

time this iterates it’s going to print zero because it’s going to print r13 and then it’s

going to print a new line so that the cursor goes to the next you know line of the terminal

so that’s all the body does it just kind of like prints the current number with an arrow and does

a new line and then at the very bottom of the loop body we just sort of maintain the for loop this is

for loop this is going to be the update part so like let’s see maybe scooch this up a little bit

the update part where we have let’s see on the very right side of the for loop which is like i

plus plus or in more assembly speak increasing the counter variable so i’m just going to increase r13

and then that way the loop can progress you know we’re always looking at r13

to decide if we need to stop or not you know we’re comparing r13 to r12

So we’re just increasing at the very bottom of the loop and then we unconditionally jump back up to the top.

Probably a better idea to unconditionally jump back up to the top because maybe the jump to the top is very very far and if it’s greater than 128 bytes it won’t work.

So the regular jump instruction doesn’t have that limitation. So now we’re jumping up to the loop top.

So you can imagine now that you know we’re not going to the initialization part. That would be bad.

We’re just jumping up to the top here where we immediately ask you know are we done?

If we’re not done, we jump into the loop body and print another number.

And then at the very bottom of the body, we say, all right, increase the counter and then jump back up to the top.

So this is a simple for loop, but you can see what it’s doing, right?

It’s just going to be printing a number over and over again as the number increases.

And then eventually it’ll stop when it hits the correct number.

The last thing we need is the loop done label.

If you look back up at the top here on line 92, if R13 was not less than R12,

less than r12 then execution would fall through to line 92 and there is our unconditional jump

instruction basically saying if r13 is not less than r12 then we’ll jump to the loop done label

which means we’re just totally finished with this loop so we have to make that real fast

and all it’s going to do is just basically say goodbye it’s just going to print a message to

to the restoration functions.

Oh, did I ruin my return somewhere?

Uh-oh, what did I do wrong?

I lost my return statement.

Did I accidentally delete that somehow?

That’s a bad program.

Or did I not even…

Hmm, I wonder if it like…

I wonder if I didn’t have my return statement

and it fell through into the CRLF function

and then the CRLF function returned to the caller

to the caller on behalf of the for test function I don’t even know only all only

the spirits know at this point I don’t know leave a comment or something if

you know what happened but every function has to have its own return for

sure so you know the loop done label is usually where you want to jump to when

you know the for loop is finished or the while loop is finished when it comes to

saying goodbye it probably would be a little bit more clear of me to add an

you know for test you know say goodbye just so that I that I remember that this

is this is the place where we’re done and this other place this is just

something else that’s happening maybe I’m doing more instructions or more

operations or calling a function or whatever so obviously if I did it this

way then the loop done label would just end up falling through to the goodbye

label and it would be fine but it’s just more visually clear I’m gonna take it

Anyway, so at this point we might have a program that actually works.

Let’s see if it does.

What else do I need to add?

No, I think we’re done with that.

Okay, let’s try it.

So we’ll do a make run and we’ll enter the number five and let’s see if it works or it

crashes.

It worked on the first try.

So I had a solution though.

Not fair, but I could have typoed.

Anyway, so it says we entered a five, the loop will print from zero to N minus one.

print from zero to n minus one so we should see from zero to four and so then every iteration of

the loop it’s just that little message we’re just printing a zero printing one printing a two you

know the number increases because we did did that little inc instruction the increase instruction

we unconditionally jump to the top of the loop where we decide if we’re supposed to uh finish

you know be done with the loop by jumping to the done label eventually after we uh let’s see

it prints this four here it’ll do the increase instruction at the bottom of the loop’s body

and then it’ll jump to the loop’s top then the loop’s top will see that it’s a five because we

just increased the four it will see that five is definitely not less than five so that’s a false

which means execution will you know fall through where the heck is that it’ll fall through to the

line 92 jump instruction which is just the loop being done so that’s here where it says goodbye

says goodbye and then we have successfully implemented a basic for loop

all right so thank you so much for watching this video I hope you learned

a little bit and had a little bit of fun I will see you in the next video happy

coding and happy studying hey everybody thanks for watching this video again

from the bottom of my heart I really appreciate it I do hope you did learn

hope you did learn something and have some fun. If you could do me a please, a small little favor,

could you please subscribe and follow this channel or these videos or whatever it is you do on the

current social media website that you’re looking at right now. It would really mean the world to

me and it’ll help make more videos and grow this community. So we’ll be able to do more videos,

longer videos, better videos, or just I’ll be able to keep making videos in general. So please

and subscribe. You know sometimes I’m sleeping in the middle of the night and I just wake up because

I know somebody subscribed or followed. It just wakes me up and I get filled with joy. That’s

exactly what happens every single time. So you could do it as a nice favor to me or you could

you could troll me if you want to just wake me up in the middle of the night just subscribe

and then I’ll just wake up. I promise that’s what will happen. Also if you look at the middle of the

screen right now you should see a QR code which you can scan in order to go to the website which

at the bottom of this video and it’ll take you to my main website where you can just kind of like

see all the videos I published and the services and tutorials and things that I offer and all

that good stuff and if you have a suggestion for clarifications or errata or just future videos

that you want to see please leave a comment or if you just want to say hey what’s up what’s going on

you know just send me a comment whatever I also wake up for those in the middle of the night I get

I wake up in a cold sweat and I’m like,

it would really mean the world to me.

I would really appreciate it.

So again, thank you so much for watching this video

and enjoy the cool music as I fade into the darkness,

which is coming for us all.

Thank you.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply