Skip to playerSkip to main content
  • 16 hours ago
Quick practical guide showing how to implement a classic for loop (i=0; i
Transcript
00:00Hey there! In this video, I'm going to teach you how to implement for loops in YASM x86-64 assembly.
00:07Although, if you're using a different type of machine or a different assembler, this video should still be useful to you
00:12because it's mostly about the concepts involved in implementing a for loop.
00:23Okay, so for starters here, what am I even talking about? Let's do...
00:27What the heck are you even talking about dude?
00:29Imagine in a higher level language we have a for loop here.
00:33And so we have like for size type i equals zero, i is less than 99, i++, right?
00:39Probably most programmers looking up assembly on the internet probably are interested in
00:45or probably already know how to implement for loops in C++.
00:49So let's just pretend that you do.
00:51And so inside of your for loop, we'll do stuff.
00:53And what happens here is, well, you know, this for loop is going to run 99 times.
00:58It's going to start at zero.
01:00And, you know, so we have like an initialization part right here.
01:04Maybe I should copy paste this and kind of break down the parts.
01:07We have an init part here for the for loop.
01:09We'll say init part.
01:11And then here we have a check part.
01:13We'll continue to loop as long as this expression is true.
01:16You can make a big complicated expression if you want to, but we'll just keep it simple for this video.
01:20So I'll call this the check part.
01:22And then we have sort of an update or a maintenance part.
01:25So I'm going to call this the update part where we increment our counter variable, move pointers,
01:31even call functions, do whatever it is you think you need to do to update the loop so that it runs it,
01:36you know, so that the loops don't actually have to be integers.
01:39But in this case, I think it's better.
01:43It's easier to understand what the loop is doing if we just kind of break down these parts anyway.
01:48So what is really a while loop?
01:50I'm sorry.
01:51What is a for loop?
01:52But a while loop that breaks and has break has like a nit logic and breaking logic and checking logic just in specific places.
02:00Imagine this.
02:01What 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.
02:09I'm going to initialize a variable size type I equals zero, right?
02:14That's the initialization part.
02:15That'll only happen one time.
02:17It won't be part of the loop body.
02:19And 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.
02:25So I'll just say while I is less than 99.
02:28And then for the update part, we just have to stick that inside of the while loop somewhere.
02:33Depending on your logic, you might want to put it at the top or the middle or the bottom.
02:37I'm going to put it at the bottom because I'm going to expect that it happens right before we do the next check.
02:43So I'm going to maybe do a comment here and call it the update part and I'm just going to increase I.
02:49So maybe if I update this code to print something, it'll seem a little bit more clear.
02:57value of I is and then I'll just say I and L and then I'll copy paste that to here.
03:04And then I can also put this inside of the while loop.
03:07And now we have transformed our for loop into a while loop.
03:14Once you know how to 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.
03:22So I should again say that there are lots of parts.
03:25I 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.
03:34So for example, implementing a while loop is in another video.
03:38So if you don't already know how to implement while loops, if you don't know how to use conditional branching or unconditional jumps,
03:44if 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,
03:51then you should probably check out my other videos first.
03:53So for now, I'm just going to assume that you know how to implement a while loop.
03:56And really the lesson is, hey, just take your for loop and convert it into a while loop.
04:02And then you can implement the while loop pretty easily.
04:05That's the secret as far as I'm concerned.
04:08So imagine this now, let's do some assembly code.
04:11So I have a source code file here called looper.asm for assembly.
04:17And you can imagine that I have a hybrid program running under the hood.
04:21I'm not going to show you all the code involved.
04:23I'm not going to show you the make file or the C++ driver that calls on this module.
04:27We're just going to write the assembly here.
04:28So, you know, if you're writing pure assembly at home to practice, that's fine.
04:33Just keep in mind, there's like a few things under the hood that I'm not showing in this specific video.
04:38So first off, I'm going to copy paste my data section of my assembly program.
04:43The first thing to note is we have a bunch of C strings here.
04:48We're basically going to be telling the user, hey, we're going to begin the for test.
04:52Maybe I should have capitalized for I'll leave it.
04:55And then we're going to prompt the user for a number.
04:57We're going to say, please enter a number.
04:59The loop will print from zero to the number minus one, which is like the typical for loop that you usually write in the most basic case in the one that I just wrote.
05:08And then we're going to have a little prefix.
05:11We'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.
05:16So if the user enters a 10, it's going to print the arrow zero and then arrow one arrow two all the way up to arrow nine.
05:23And then when we're done, we're going to print an ending message.
05:27So this is nothing new if you know assembly already, just C strings that will print with system calls.
05:34See my other videos if you don't know how to do that.
05:36And then a CRLF string, just basically doing a new line, a carriage return new line feed on the system.
05:43And then we're going to output using system call code one, and we're going to use file descriptor one so we can print a standard output.
05:50Okay, so now the real fun begins.
05:54Let's start our text section, which is where the instructions of our assembly program go.
05:59So I'm going to do text section section text right there.
06:04And I'm going to use two external functions to just help me input and output numbers to the user.
06:11If you wanted to, you could use a system call that just inputted a character.
06:16And then you could just kind of like loop printing various characters.
06:20And 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.
06:29Or if they hit, you know, F, it'll just print F all the way to Z.
06:33You could do that without using an external library for printing integers.
06:37This video is not about this library right here, so I'm not really going to go over it.
06:41But, you know, you could hard code the start and end points when you're practicing.
06:46You could use a different library or a different function call to get the inputs.
06:50You could use a system call just to input one character.
06:53Or you could, you know, use a hybrid program to utilize print F and scan F.
07:00Either way, I'm just going to be using these two functions just to like get input and output.
07:05It's not really part of the idea of looping.
07:08So now let's start our entry point.
07:12Our function is called looper.
07:14Since this is a hybrid program, you can imagine there's a C++ module elsewhere calling on the looper function.
07:21And so that's why I mark it as global so it can be called upon.
07:24And then I have another function called Fortest.
07:26I don't really know why I chose to do it this way, but I wanted to make another function that was called upon by our entry point here.
07:33So the looper function really doesn't do anything except recall the Fortest function.
07:37So now let's start the Fortest function.
07:39Actually, maybe this is where the fun begins.
07:41So I'm going to put it down here.
07:43And so you can see the signature.
07:47It doesn't take any arguments.
07:48It doesn't return anything.
07:49It just does stuff.
07:50And then I have a note to myself.
07:51This is how we're going to use the registers.
07:53We're going to use R12 for the user's number.
07:56And then we're going to use R13 to keep track of where we're going.
08:02So let's see.
08:05I'm going to start by saying let's preserve R12 and R13 because you have to respect the application binary interface, the ABI.
08:14And that designates R12 and R13 as Kali saved registers.
08:18If I don't preserve those and my program is even a little bit complicated, I'm probably going to be debugging forever or I'm going to just crash my program for no reason.
08:27So I'm going to just do a push pop pair.
08:31Notice how the pops are in reverse order.
08:33This 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.
08:42It just prints out the CRLF string with a system call.
08:47That's all it does.
08:48Very simple.
08:49But then that allows me to just call CRLF.
08:51OK, so do I even need CRLF in this program?
08:56I think I just modified this.
08:58Maybe I don't even need it anymore.
08:59No, I guess I do.
09:00The first thing we'll do is we'll print an introduction message to the user.
09:05So inside of the for test, we'll just use a system call to print out, you know, a welcome message to the user.
09:11And then I'm going to call CRLF, which will just give us a new line.
09:15And yeah, you can hard code, you know, the 13, 10 at the end of these strings, but I don't really like doing that.
09:21OK, so we should have a working program at this point.
09:24Let me see if it actually does work clear and make run.
09:30OK, so the driver prints a little welcome message.
09:33You don't see the driver code, but that's what it's doing.
09:35And then the for test prints the welcome message that we just added.
09:39And then the driver lets us know it's retained control and then it's responsible for returning to the operating system for us.
09:45OK, so then the next thing we're going to do is we're going to ask the user for a number so that we know how many times to loop.
09:53And again, you could hard code this number if you don't want to do IO right now.
09:57You could even print a character a certain number of times if you don't want to even deal with printing an integer.
10:04But I'm going to ask the user for a number that's going to be the prompt string.
10:08And if we run it again, now you should see it asks the user for a number.
10:14So it's going to say, please enter a number.
10:16The loop will print from zero to N minus one doesn't actually ask for the number, though.
10:20It doesn't actually, I guess, take the number.
10:22So 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.
10:30And I'm going to receive that back in RAX and I'm just going to save RAX into R12.
10:35So R12 is now going to be the number that the user inputted.
10:38And that's why up here I have it designated as the user's number.
10:42So really not a big deal.
10:44But, you know, if we run it again, it'll ask for a number and then it won't do anything else.
10:48It'll just kind of quit.
10:50Okay.
10:51So now we can implement our for loop.
10:54This is going to be a little tricky.
10:56So we're going to start off with the initialization part.
10:59Remember, we had several parts here.
11:01If I just kind of drag this off to the side, maybe pin it up to the top so we can see it.
11:06We had many parts.
11:08And I guess we're kind of covering that, aren't we?
11:13If I move it a little bit to the side.
11:15So remember that for loop, it's got an init part and a check part and an update part.
11:22And 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.
11:28And so I made another comment here with for and then empty parentheses just to denote that some comments that come below are going to actually be parts of, I guess, the top of the for loop.
11:42So now I'm going to make a label here.
11:45And 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.
11:53And that kind of helps me keep track of my symbols a little bit more easily, especially if I have a large module.
11:59The symbols are less likely to overlap if I prefix them with the function names.
12:04So here for test is the name of the function we're in.
12:07So everything is going to be for test underscore something.
12:10And since I'm only doing one thing inside of the for test function, I'm just going to have a suffix only for the most part.
12:16But you can imagine if you had more parts inside of your function and it started getting a little clutter 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.
12:34Although this is assembly, it gets really hard, really fast.
12:37So if your function is even a little bit complicated, you should probably consider breaking it up into multiple functions if you can.
12:43We can't really do that at this point because it's just a for loop, but keep that in mind.
12:48Okay, so we're going to initialize.
12:50Remember, 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.
12:58So I'm just going to do that here.
12:59I'm going to say move zero into R13.
13:02So basically R13 is equal to zero.
13:04That's the first part, the update part where we set size type I equals zero.
13:11In fact, maybe I could do another copy paste to this, where instead of using a size type, we'll just say that the register R13 equals zero.
13:22I 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.
13:29We'll keep going as long as R13 is less than R12.
13:32And then we increase R13.
13:36So I'm just going to put ink R13.
13:38So it looks more assembly like even though this completely and totally would not compile in C++.
13:43I hope that this helps your understanding a little bit.
13:46So, yeah, we can do everything except for just the increase part at the very top.
13:51I'm going to choose to increase it at the bottom.
13:53If you wanted to, I guess you could start off R13 as a negative number and then increase it at the top.
13:58But I personally don't feel that's like very clean.
14:01It also forces you to use signed integers.
14:03Maybe you wanted to use an unsigned integer so you could get like a gigantic maximum number that you looped up to.
14:10I don't know.
14:11So we'll just initialize here and we'll say R13 is equal to zero.
14:16The init part should not be part of the actual like looping.
14:20Like every time you loop up to the top of the for loop, you should not repeat that part again.
14:24It should only happen once.
14:26So the next label that I 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.
14:37So maybe I should say that's why this is named to underscore loop top.
14:43And I don't know, you don't have to do camel casing in your labels, you know, you could just do loop in it or whatever, but I'm just choosing to do it this way.
14:52So at the top of our loop, we'll be checking to see if we should continue.
14:56Remember that was the check part, right?
14:58So we're going to check to see that R13 is still less than R12.
15:02If it is, we'll continue with the for loop.
15:04If it's not, then we jump out of the for loop.
15:07So 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.
15:16And the false case where R13 is not less than R12, that should probably end up being a much longer jump.
15:23And depending on how big your loop is, maybe that jump is too long, too far away for a conditional branching instruction to reach.
15:32If 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.
15:41If you try to go further than that, the assembler will actually stop and block you from finishing your compilation.
15:46It'll say, I think it's like jump out of range or something like that.
15:52So you want to, you want to try to keep the short jump points with your conditional branches.
15:59And then in the false case where the conditional jump doesn't actually, the conditional branch doesn't actually do anything.
16:06Then it falls through to the next instruction where you will have an unconditional jump.
16:10And remember the unconditional jumps, they don't have a limitation of 128 bytes.
16:15They can jump like all over the place, like they can jump anywhere basically.
16:18So that means if you think about it, we come in to the loop top right here.
16:24We immediately do a compare instruction and a conditional branch.
16:28So 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.
16:40And if not, we will end up falling through to line 92 where there's just an unconditional jump instruction that just says,
16:47all right, let's jump all the way down to being done, which could be very far away for all we know.
16:53Okay. So we've done that.
16:55Now 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,
17:02which in this case will just be, you know, printing a number every time, every time we loop and then increasing that number.
17:09So I'm going to do a little like new line there.
17:13I'm going to paste the loop body.
17:14Notice also that I've added little comments to help remind myself that this is actually the loops body.
17:19So for test loop body that takes care of the branching instruction, hitting on that and actually going into the body.
17:27And then later we're going to have to implement a label for the loop being done.
17:31But for now, we'll just say the body.
17:33What does it do?
17:34It just prints a little message to the user.
17:37If you look at the message for current number string, if I go up real fast message for current number, it's just an arrow.
17:44So the user is going to see an arrow and then their current number, I guess of the loops current number.
17:49And then every time it loops, it's just going to continue printing that arrow with a number on it.
17:54So we're doing that.
17:55And 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, is just the first integer argument for a function call.
18:10So I'm just going to call this other function here, which is not part of the video to just say, hey, please print this number for me.
18:16So the first time this iterates, it's going to print zero because it's going to print R13.
18:22And then it's going to print a new line so that the cursor goes to the next line of the terminal.
18:28So that's all the body does.
18:29It just kind of like prints the current number with an arrow and does a new line.
18:33And then at the very bottom of the loop body, we just sort of maintain the for loop.
18:40This is going to be the update part.
18:42So like, let's see, maybe scooch this up a little bit.
18:46The update part where we have, let's see, on the very right side of the for loop, which is like I++ or in more assembly speak, increasing the counter variable.
18:56So I'm just going to increase R13 and then that way the loop can progress.
19:01You know, we're always looking at R13 to decide if we need to stop or not.
19:05You know, we're comparing R13 to R12.
19:08So we're just increasing at the very bottom of the loop.
19:11And then we unconditionally jump back up to the top.
19:14Probably a better idea to unconditionally jump back up to the top because maybe the jump to the top is very, very far.
19:19And if it's greater than 128 bytes, it won't work.
19:22So the regular jump instruction doesn't have that limitation.
19:25So now we're jumping up to the loop top.
19:26So you can imagine now that, you know, we're not going to the initialization part.
19:30That would be bad.
19:31We're just jumping up to the top here where we immediately ask, you know, are we done?
19:36If we're not done, we jump into the loop body and print another number.
19:39And then at the very bottom of the body, we say, all right, increase the counter and then jump back up to the top.
19:44So this is a simple for loop, but you can see what it's doing, right?
19:47It's just going to be printing a number over and over again as the number increases.
19:51And then eventually it'll stop when it hits the correct number.
19:55The last thing we need is the loop done label.
19:58If you look back up at the top here on line 92, if R13 was not less than R12, then execution would fall through to line 92.
20:08And 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.
20:18So we have to make that real fast.
20:24And all it's going to do is just basically say goodbye.
20:26It's just going to print a message to the user with a system call, call a CRLF and then fall through to the to the restoration functions.
20:35Oh, did I did I ruin my return somewhere?
20:37Oh, what did I do wrong?
20:39I lost my return statement.
20:41Did I accidentally delete that somehow?
20:44That's that's a bad program.
20:46Or did I not even wonder if it like I wonder if I didn't have my return statement and it fell through into the CRLF function.
20:58And then the CRLF function returned to the caller on behalf of the for test function.
21:05I don't even know.
21:07Only only the spirits know at this point.
21:09I don't know.
21:10Leave a comment or something if you know what happened.
21:12But every function has to have its own return for sure.
21:15So, 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.
21:22When it comes to saying goodbye, it probably would be a little bit more clear of me to add an additional label specifying, you know, for test, you know, say goodbye.
21:31Just so that I that I remember that this is this is the place where we're done.
21:36And this other place, this is just something else that's happening.
21:38Maybe I'm doing more instructions or more operations or calling a function or whatever.
21:43So 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.
21:49But it's just more visually clear.
21:52I'm going to take it out, though, because I don't have that in my solution.
21:58Anyway, so at this point, we might have a program that actually works.
22:01Let's see if it does.
22:03What else do I need to add?
22:04No, I think we're done with that.
22:05OK, let's try it.
22:08So we'll do a make run and we'll enter the number five and let's see if it works or it crashes.
22:14It worked on the first try.
22:16So I had a solution, though.
22:17Not fair, but I could have typoed.
22:21Anyway, so it says we entered a five.
22:23The loop will print from zero to n minus one.
22:25So we should see from zero to four.
22:27And so then every iteration of the loop, it's just that little message.
22:31We're just printing a zero, printing one, printing a two.
22:34You know, the number increases because we did that little INC instruction, the increase instruction.
22:39We unconditionally jump to the top of the loop where we decide if we're supposed to finish, you know,
22:44be done with the loop by jumping to the done label.
22:47Eventually, after we, let's see.
22:51Eventually, when it prints this four here, it'll do the increase instruction at the bottom of the loop's body
22:57and then it'll jump to the loop's top.
22:59Then the loop's top will see that it's a five because we just increased the four.
23:03It will see that five is definitely not less than five.
23:07So that's a false, which means execution will, you know, fall through.
23:12Where the heck is that?
23:13It'll fall through to the line 92 jump instruction, which is just the loop being done.
23:18So that's here where it says goodbye.
23:21And then we have successfully implemented a basic for loop.
23:25All right.
23:27So thank you so much for watching this video.
23:29I hope you learned a little bit and had a little bit of fun.
23:32I will see you in the next video.
23:35Happy coding and happy studying.
23:37Happy coding.
23:38Happy coding to the Lord.
23:39Hey, everybody.
23:40Thanks for watching this video again from the bottom of my heart.
23:43I really appreciate it.
23:44I do hope you did learn something and have some fun.
23:46If you could do me a please, a small little favor.
23:48hope you did learn something and have some fun uh if you could do me a please a small little favor
23:53could you please subscribe and follow this channel or these videos or whatever it is you do on the
23:59current social media website that you're looking at right now um it would really mean the world to
24:03me and it'll help make more videos and grow this community so we'll be able to do more videos
24:08longer videos better videos or just i'll be able to keep making videos in general so please
24:13do do me a kindness and uh and subscribe you know sometimes i'm sleeping in the middle of the
24:18night and i just wake up because i know somebody subscribed or followed it just wakes me up and i
24:23get filled with joy that's exactly what happens every single time so you could do it as a nice
24:27favor to me or you could you could troll me if you want to just wake me up in the middle of the night
24:31just subscribe and then i'll i'll just wake up i promise that's what will happen also uh if you
24:37look at the middle of the screen right now you should see a qr code which you can scan in order
24:41to go to the website which i think is also named somewhere at the bottom of this video
24:45and it'll take you to my main website where you can just kind of like see all the videos i published
24:50and the services and tutorials and things that i offer and all that good stuff and uh
24:57if you have a suggestion for uh uh clarifications or errata or just future videos that you want to see
25:03please leave a comment or if you just want to say hey what's up what's going on you know just send me a
25:08comment whatever i also wake up for those in the middle of the night i get i wake up in a cold
25:12sweat and i'm like it would really it really mean the world to me i would really appreciate it so
25:18again thank you so much for watching this video and um enjoy the cool music as as i fade into the
25:26darkness which is coming for us all
25:36so
25:38so
25:46so
25:48so
25:50so
26:01so
26:03so
26:13so
26:23so
26:25so
26:27so
26:40so
26:42so
26:44so
27:00so
27:02so
27:04so
27:23so
27:25so
27:27and
27:49so
27:51so
28:02so
28:14so
28:16so
28:26so
28:28so
28:30so
28:32so
Comments

Recommended