Skip to playerSkip to main content
  • 4 months ago
Want to master command line arguments in pure x86-64 YASM assembly on Linux? This video breaks down how to access argc and argv directly from the stack, without GCC libraries. Follow along as we write a program to loop through and print user-provided arguments, complete with a visual stack explanation. Whether you're new to assembly or leveling up, this tutorial offers clear, practical insights for coding low-level programs. Check out my other videos for more assembly tips, and subscribe for more coding goodness!

Introduction to Command Line Arguments 00:00:00
Target Architecture and Assumptions 00:00:04
Recap of Command Line Arguments 00:00:56
Accessing Arguments in Pure Assembly 00:01:47
Program Structure and Data Section 00:02:19
Stack Pointer and Argument Count 00:04:16
Accessing Argument Vector (argv) 00:07:14
Looping Through Arguments 00:12:16
Incrementing to Next Argument 00:16:45
Visualizing the Stack 00:19:24
Running the Program with Arguments 00:21:56
Conclusion and Call to Subscribe 00:23:48

Thanks for watching!

Find us on other social media here:
- https://www.NeuralLantern.com/social

Please help support us!

- Subscribing + Sharing on Social Media
- Leaving a comment or suggestion
- Subscribing to our Blog
- Watching the main "pinned" video of this channel for offers and extras
Transcript
00:00hey there let's talk about accepting command line arguments in a pure assembly program
00:04written for x8664 aka amd yasm assembly
00:16on linux anyway so uh there are going to be a lot of topics that i that i sort of
00:21mention in this video that are not actually covered in this video so if you feel yourself
00:25getting lost like for example if you don't know how to program an assembly in the first place
00:30if you don't know what command line arguments are if you don't know the terminal things like that you
00:34probably want to check out my previous videos because they will be explained in detail
00:39for now i'm just going to assume you know how to do all this basic stuff and the only thing that i
00:42need to show you is how to write a program in yasm assembly that can grab your command line arguments
00:49so you know just to do a quick recap of what i'm even talking about if we have a program named echo
00:56we can launch it with no arguments it doesn't do anything but we can give it some arguments we can
01:00say hello and then we can say goodbye and that's two arguments that i'm giving to echo echo will grab
01:08onto the arguments it was given it's actually going to receive three arguments the index zero argument
01:14being the name of itself its own program and then the next two arguments being the stuff that i typed
01:20after the program but you can see that it somehow figured out how to grab these two arguments as
01:24strings and print them right so imagine you have an assembly program and you want the user to be able
01:31to launch your program and add arguments at the end of the command line and have your program behave in
01:37some certain way according to what the user wants the question then becomes how do you access those arguments
01:44it's a little bit easier in gcc look at my other video that i posted about the topic for gcc linked
01:50assembly programs it's a little bit easier you pretty much just look at rdi and rsi to get your argc
01:56and your character pointer array when you're dealing with pure assembly though the gcc libraries don't
02:02bundle up the command line arguments in a really convenient way for you you've got to look for them
02:06elsewhere it's honestly not that much harder it's just a little feels a little weird i think at least for me
02:12i was hoping to see the arguments in a register and i did not but anyway so here's my program again
02:19this is not an assembly programming video if you need to know how to program assembly see my other
02:23videos for now i'm just going to quickly go over it i've got my data section in yasm i am printing out
02:29a couple of strings or i i have a couple of strings defined i'm saying like the module has started i'm
02:36going to begin printing arguments i have some system call codes so that i can write uh just to
02:42standard output and so that i can exit the program this is pure assembly so we don't actually return
02:47from main we just get jumped into and then we call exit normally and then here's the standard output
02:54pipe again another video covers that and then i've got the exit success code again another video covers
03:00that but basically you know exiting zero is usually what you do for success then i've got the text
03:06section which holds all my assembly instructions and this is my entry point we don't really need to
03:12push and pop these registers because we're just going to exit the program when we're done
03:16it's totally fine we would need to preserve collie saved registers if we were jumping into a main function
03:22or if this was a different function that was being jumped into but we're not so we don't have to
03:27any way here's my entry point the underscore start for a pure assembly program and then i'm going
03:33to grab the incoming arguments when you're linking with gcc which we're not doing here in
03:39this video then the arguments come in very easily they just come in argc shows up in rdi and arg
03:47sorry argc comes into rdi and the character pointer array comes in as rsi so you can imagine
03:54uh in gcc this would be integer main and then integer argc character pointer array argv right
04:06hopefully you've done this in a higher level language so you have a better idea of what i'm
04:09talking about if not i guess that's okay it will still allow you to grab even if you don't understand
04:14this in c plus plus so argc is actually the stack pointer the stack pointer register rsp always tells you
04:24you know where the top of the stack is like what's the last piece of data
04:28that we actually have sitting on the stack so that's going to be the count of arguments argc is
04:33always going to be the stack pointer so if you dereference the stack pointer register then what
04:41you're doing is you know the stack pointer register actually points to memory locations within the stack
04:47so if the memory location that it's looking at is where argc is stored then you dereference it with the
04:52brackets and you'll actually get argc so right away i'm just going to steal argc off the top of the
04:58stack and this is a good idea to do right away because if you start doing other stuff you might end
05:04up modifying the stack especially if you start calling functions and things like that and and these
05:09these pieces of information will be will be lost or they'll be a lot harder to find so right away i'm
05:14just going to say argc goes directly into r12 and i have a little comment reminder for myself at the top
05:19saying r12 is now argc same thing for uh r13 i'm going to say that's a pointer to my character pointer
05:30array i talked about this in depth on my other video where we talked about gcc command line arguments
05:36to an assembly program but basically if you look at uh if you look at argv right here it's not just a
05:43pointer and it's not just an array it's a pointer to an array and if you recall in higher level languages or
05:48just i guess anything an array itself is a pointer because argv the symbol let's say we were in a
05:56higher level language argv can only point to one thing so it's going to point to the very beginning
06:02of your array if that makes sense but the beginning of your array is not going to be one string like
06:09one argument that the user gave you because the user could give you many arguments instead it's an array
06:15of pointers so it's a character pointer array meaning argv is a pointer to a pointer
06:25the first item in any array is what is pointed to by the symbol so like imagine if we had just for the
06:32sake of argument imagine if we had an integer array let's say we had like 500 integers in like a c plus
06:40plus program so the symbol a is what i'm trying to say the symbol a is really a pointer that points
06:45to the first integer in that array and then later of course you can dereference that pointer with some
06:50sort of an index to get the index 5 integer or the sixth integer right so the symbol is both the array
07:01and a pointer to the first item or i guess you could say it's both a pointer to the array and a
07:06point to the first item because it's kind of the same thing so that means if we uh if we grab argv
07:14then we'll be grabbing a pointer if we then dereference that pointer it would tell us where
07:21another pointer is and then that other pointer would be a would point to a string representing
07:28the first argument so we'll explain that more as i do this loop i'm going to i'm going to show you some
07:33code that actually loops through all the arguments anyway the thing about where to find that argv is
07:39it's just the next pointer or i guess it's the it's the next item that the stack holds so remember i
07:47told you that rsp when this when this function comes in rsp is a pointer to wherever we're we're
07:53looking what memory location the top of the stack is so if we dereference that we get argc
07:58well we just need to go find the next previous item in the stack and then dereference that so
08:05that we can get the first pointer or or argv you know the the first pointer to a pointer or the first
08:14the first double pointer in your array of pointer of pointer to pointers uh why am i doing plus eight
08:23this might actually make sense as is but it's important to understand that when you
08:26add stuff to the stack you're actually decreasing the memory locations uh that you are pointing to
08:31so like if i if i increase a stack this is not a stack video there's other videos that i have for
08:36that um if we add something to the top of a stack you imagine the stack growing visually in a in a
08:43vertical direction like it's growing up right but inside of the computer the memory locations are
08:48actually going down so keep that in mind that means if we're looking at the stack pointer and we're adding
08:54eight what it's saying is that we're looking back into memory that was already added for the stack
09:01so that's like like if we grew the stack that would be subtracting from the memory location so like
09:09looking further up in the stack would be subtracting from the memory location because the stack grows
09:14upward in the abstract but downward in memory locations so that means if we add eight that means
09:20we're going in the other direction we're looking downward into the stack so what that means is that
09:24the top two items on the stack are first argc and then second that first pointer you know the argv
09:32argument and that's how we access it with plus eight why is it a plus eight instead of plus something else
09:37because all pointers on 64-bit systems are 64-bit integers and 64-bit integers are eight bytes
09:45if we if we're talking about eight bytes uh sorry if we're talking about eight bits per byte
09:50so this is just how you access it what about this other thing going on here what's this lea
09:54instruction usually you see a move instruction right so
10:00we uh we basically want to look at the stack pointer but look one level lower and you know each item
10:08on the stack is also going to be eight bytes we want to look one item lower on the stack
10:14and then we want to dereference it but we don't want to um dereference and store the dereferenced
10:20value we still want to grab the actual pointer the thing is i shouldn't have said dereference in the
10:25first place these are dereferencing brackets right so like up here on line 46 when you put brackets
10:32around rsp it dereferences whatever value rsp holds so therefore when you put brackets around this you kind
10:38of expect that you're going to be dereferencing right but we don't want to dereference we just want the
10:42original address that it's showing us so the problem with this is that when we say rsp plus
10:51eight we can't actually do a mathematical formula unless we're inside of brackets which means we
10:58can't do them in a move instruction without accidentally dereferencing and and losing a
11:03pointer to the actual array of pointers if we dereference like this we would just end up with
11:08you know a pointer to one string so the way around this is instead of using the move instruction we
11:13use the lea instruction the lea instruction allows us to put a formula inside of brackets so that the
11:20assembler won't get confused but then it won't put the dereferenced value into r13 it'll just
11:28put the actual value of whatever we see
11:30with that formula meaning it'll give us the memory location of the item sitting one under the top of
11:38the stack trust me on this at this point r13 is now the memory location of the of the item sitting one
11:45underneath the top of the stack and then we can de-reference that later in order to look at all of
11:50our arguments so the next part of our code is just going to print an intro message so there's like this
11:57intro string up here hello and um i'm basically going to call a custom function that i made to just
12:04sort of uh print another thing saying we're about to begin printing don't worry about this code right
12:10here this is not the point of the video i just made a custom function that just kind of helped me print
12:15don't worry about that the real meat of this video is that we're going to loop through all arguments
12:21and just print every single argument that the user provided so you can imagine this is maybe the top of
12:26a while loop here notice how oh i forgot to replace main with uh start with start i had another version
12:34of this program that used main so let's just pretend we have this is called the main loop instead of the
12:39the main functions loop anyway so main loop initialize the first thing i'm going to do is
12:44i'm going to initialize the loop by saying we're looking at index zero okay no problem so we're looking
12:51at index zero we want to do that we want to look at all the arguments you know we want to look at
12:55index zero and index one and index two and we just want to keep going until we're out of arguments
13:02remember that we also have the number of arguments coming from rxc now sitting in r12 so that means
13:09if we have a counter that starts at zero with r14 and then we know how many arguments there are in r12
13:15we should be able to know when the loop stops so just a reminder that you know the loops here
13:22the arrays here are zero based indexed or zero index based which means for example if we have three
13:30arguments here if we include the original program that's three arguments but the array of arguments
13:36is going to have indexes zero and one and two which means the last valid index is going to be two or
13:43the size minus one think about that if you have five arguments the last index that is valid is going
13:49to be four size minus one because it's zero based so we can use that logic to figure out if we're done so
13:55we start off with an index of zero here and then at the top of the loop i'm just going to quickly
13:59ask are we done how do we know if we're done we compare the current index we're looking at with
14:05the count and we say if the current index we're looking at is greater than or equal to the count
14:11then we know we're already done we don't need to look at any more indexes why am i saying is is the
14:16index greater than or equal to the count because remember if we have five arguments then the last
14:22valid index is four therefore if we find ourselves looking at index five we know we're already done
14:29five is equal to or greater than five but four is not equal to or greater than five so that's why
14:34i'm using this logic here i'm saying if we're done then jump to the done label basically what's the
14:40done label it's main loop done all it really does is it says goodbye and then it just exits the program
14:46with a system call again i have other videos that explain system calls and all that stuff
14:53so if we're done we uh we jump down to the done area but if not then execution will fall through
14:58to this next loop or sorry this next uh label which is not necessarily we don't really need a label
15:04there but i i like to put i like to put it there just to help myself remember this is what it looks
15:09like in terms of a while loop you know i have like here's the top of the while loop here's the little
15:13comparison part of the while loop here's the body like the opening braces of the while loop and then
15:18here's sort of like the closing braces i just like to do that but anyway after we decided that
15:23we are not done and we drop through to the next actual instruction we're just going to print the
15:28next argument so what's the next argument we will dereference r13 remember up here we took the second
15:38item sitting like you know one under uh the top of the stack and we just stuck it into r13 so
15:43this is r13 is now the address of the second item on the stack if we dereference it then that's going
15:52to give us a a pointer to our um sorry it's going to give us a pointer to the first item
16:01to the first string i should say to the first string
16:04uh the the the string of the first argument so if we dereference you know let me say this one
16:14more time just to make sure that i'm clear on this the second item you know the item right under the
16:21top of the stack that's going to be a pointer to the first argument string so if we just simply
16:29dereference r13 then we're basically telling rdi here's a pointer to the string that we want to
16:35print okay so then i just call my helper function to print that string to standard output no problem
16:42and then we have to figure out like how do we increment to go to the next string
16:46so on the stack i think i might have been unclear earlier because gcc does it in a different way but on
16:51the stack every item underneath the the top of the stack is a is another pointer it's part of the
17:00original argv array it's another pointer to a different string so basically if i increase r14
17:08here then i'm increasing the index counter that'll help us eventually terminate but notice how here i'm
17:13adding 8 to r13 remember r13 is the second item you know the item right under the top of the stack
17:21and if i dereference that then i now have a pointer to the first argument string if i want to go
17:27one lower into the stack then i just add 8 to that register's value because again remember
17:34the stack grows downward in memory so if i increase the value then i'm sort of like going through
17:41previous items that were put into the stack so so imagine the stack here it's got like
17:45you know argc sitting on top and then underneath argc it's got a pointer to the first argument and then
17:52under that in the stack it's got a pointer to the second argument and then under that in the stack
17:56it's got a pointer to the third argument then under that it's got a pointer to the next argument and so
17:59forth so every time we want to go to the next arguments pointer the next arguments is a string
18:05pointer we just add 8 to that r13 register which was originally just pointing at the first string
18:12so again why eight because pointers are 64-bit integers therefore they are eight
18:18bytes so I'm just literally increasing the index by one and then I'm moving
18:24that register R13 to point to the next pointer that way next time I dereference
18:30it up here on line 70 I'll be dereferencing the next string and these
18:35strings don't need to be contiguous they could be located anywhere it's the
18:39stack that is contiguous but it's just full of pointers to other strings or
18:44sorry it's full of if we dereference the stack pointer at any point then we will
18:51get the address of a string so then we will get a pointer to a string this
18:57double pointer stuff sometimes I get tongue tongue-tied okay so when we're done
19:03printing and incrementing then we just jump to the top of the loop
19:07and then finally when we're done well we're done let me draw this out for you
19:12because I think the way I'm explaining it might be a little bit unclear so I just
19:15want to make sure that that I'm being totally clear on this okay so I've got
19:20my little annotator here and you can imagine here's a stack and it visually
19:25grows up we can imagine that every time we add an item to the stack it grows up
19:30like if you wanted to take a five stick it on top of the stack well then it would
19:33end up on the top of the stack right no problem oh maybe this needs to be bigger
19:39because of my pen size so let's do it like that
19:46what the heck happened I lost the whole desktop there we go so we have this and
19:52this and this and this and so there's probably some kind of a value sitting on
19:57top of the stack when we started the program RSP is a register that just has the
20:02memory location of the top of the stack you know the most recently added item we
20:07know that this was actually argc so if we dereferenced RSP
20:14that'll go to wherever argc is and get it so we can basically say that argc is
20:23sitting on the top of the stack so you know we dereference our RSP which holds a
20:28memory location to this place in memory but at that place in memory we just had
20:32an integer stored an 8 byte integer okay cool so then the next lowest I guess the
20:41next highest item or the next lower item is argc v at index 0 which is the same
20:48thing as just saying argc v remember a pointer to the array is really a pointer to
20:51the first item the next lower item is argc v at index 1 and so forth so we can just
21:00keep doing this we can keep going lower and lower and lower on the stack by
21:03adding 8 to r13 because remember r13 originally pointed you know to this item
21:09right here I don't know I'll say like r13 maybe starts off pointing to the first
21:17argument because that's the way we have it set up so every time the loop iterates
21:20if we dereference r13 then we're getting a pointer to a string which is going to be the
21:26the current argument and then when we add 8 bytes to r13 we're really just moving it
21:31down to the next pointer that we can dereference hopefully that was a little bit more clear than
21:36what I said before or maybe you're just a visual learner you know it's a good idea to try to
21:44explain things in many different ways but long story short we're going down down down further in
21:48the stack to get more arguments and we're just printing them and so now that we've explained
21:53it all we should be able to just run the program so I'm going to do clear and make run and under
22:00the hood let me just show you real fast what I've got inside of my make file under the hood when we
22:06do make run you don't need to know about big files I have a video that explains all of this don't worry
22:11but uh well I mean you don't need to know it to understand this video but you probably do need
22:16to know it notice how when I call the executable which in this case is just referred to as a
22:23variable named bin I give it some arguments I give it just some strings first arg second arg third arg
22:29fourth arg so that's the same thing as if I typed echo first arg second arg third arg fourth arg right
22:38that's what echo is doing so in the make file I'm just giving it those arguments and then our
22:43program now is looping through all of the arguments it knows when to stop because we grabbed arg c
22:49and it knows where those strings are located because the pointers to those strings are just sitting on
22:56the stack so if we deref twice we're derefing we're doing a double dereference a pointer to a pointer
23:03uh at least we could say r13 is a pointer to a pointer but the actual values sitting inside the
23:10stack are just pointers to strings um so let's just do this in a slightly different way just so
23:16you can believe me here a little bit more I'll do clear and then I'll say main because that's the
23:22name of the program that I compiled you can imagine this is could be named something else and I'll just
23:28put uh hello you are super cool now so I'm giving it one two three four five arguments in addition
23:37to main so it should print six things main hello you are super cool now so notice how it prints main
23:44hello you are super cool now all right um that's pretty much everything that I wanted to show you
23:51for the pure assembly version of grabbing command line arguments thank you so much for listening it's a
23:56little it's a little late for me the sun's starting to come up I've got to go and eat a bunch of
24:01cookies so I hope you learned some stuff and I hope you had a little bit of fun thank you so much for
24:06watching this video I will see you in the next one happy happy studying and coding and all that stuff
24:13hey everybody thanks for watching this video again from the bottom of my heart I really appreciate it
24:21I do hope you did learn something and have some fun if you could do me a please a small little favor
24:27could you please subscribe and follow this channel or these videos or whatever it is you do on the
24:33current social media website that you're looking at right now it would really mean the world to me and
24:37it'll help make more videos and grow this community so we'll be able to do more videos longer videos
24:43better videos or just I'll be able to keep making videos in general so please do do me a kindness
24:49and uh and subscribe you know sometimes I'm sleeping in the middle of the night and I just wake up because
24:54I know somebody subscribed or followed it just wakes me up and I get filled with joy that's exactly what
24:59happens every single time so you could do it as a nice favor to me or you could you could troll me if
25:03you want to just wake me up in the middle of the night just subscribe and then I'll I'll just wake up
25:07I promise that's what will happen also uh if you look at the middle of the screen right now you
25:13should see a QR code which you can scan in order to go to the website which I think is also named
25:17somewhere at the bottom of this video and it'll take you to my main website where you can just kind
25:22of like see all the videos I published and the services and tutorials and things that I offer and
25:27all that good stuff and uh if you have a suggestion for uh uh clarifications or errata or just future
25:36videos that you want to see please leave a comment or if you just want to say hey what's up what's
25:41going on you know just send me a comment whatever I also wake up for those in the middle of the night
25:45I get I wake up in a cold sweat and I'm like it would really it really mean the world to me I would
25:51really appreciate it so again thank you so much for watching this video and um enjoy the cool music
25:58as as I fade into the darkness which is coming for us all
26:02um
26:04um
26:08and
26:09and
26:10and
26:12and
26:14and
26:16and
26:18and
Be the first to comment
Add your comment

Recommended