<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>callee saved registers Archives - NeuralLantern.com</title>
	<atom:link href="https://www.NeuralLantern.com/tag/callee-saved-registers/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.NeuralLantern.com/tag/callee-saved-registers/</link>
	<description></description>
	<lastBuildDate>Sun, 08 Feb 2026 01:59:29 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://www.NeuralLantern.com/wp-content/uploads/2025/04/cropped-2025-04-04-Lantern-03-32x32.png</url>
	<title>callee saved registers Archives - NeuralLantern.com</title>
	<link>https://www.NeuralLantern.com/tag/callee-saved-registers/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Implement strlen for Null-Terminated Strings in x86-64 Assembly (YASM)</title>
		<link>https://www.NeuralLantern.com/implement-strlen-for-null-terminated-strings-in-x86-64-assembly-yasm/</link>
					<comments>https://www.NeuralLantern.com/implement-strlen-for-null-terminated-strings-in-x86-64-assembly-yasm/#respond</comments>
		
		<dc:creator><![CDATA[mike]]></dc:creator>
		<pubDate>Sun, 08 Feb 2026 01:59:27 +0000</pubDate>
				<category><![CDATA[Assembly Language]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[Computer Science]]></category>
		<category><![CDATA[Videos]]></category>
		<category><![CDATA[abi register preservation]]></category>
		<category><![CDATA[assembly language tutorial]]></category>
		<category><![CDATA[assembly length function]]></category>
		<category><![CDATA[assembly string handling]]></category>
		<category><![CDATA[assembly while loop]]></category>
		<category><![CDATA[c strings assembly]]></category>
		<category><![CDATA[callee saved registers]]></category>
		<category><![CDATA[learn assembly 2025]]></category>
		<category><![CDATA[low level programming]]></category>
		<category><![CDATA[NASM vs YASM]]></category>
		<category><![CDATA[null terminated string]]></category>
		<category><![CDATA[reverse engineering]]></category>
		<category><![CDATA[strlen assembly]]></category>
		<category><![CDATA[sys_write tutorial]]></category>
		<category><![CDATA[systems programming]]></category>
		<category><![CDATA[write syscall assembly]]></category>
		<category><![CDATA[x86 assembly linux]]></category>
		<category><![CDATA[x86-64 assembly]]></category>
		<category><![CDATA[x86-64 linux assembly]]></category>
		<category><![CDATA[Yasm tutorial]]></category>
		<guid isPermaLink="false">https://www.NeuralLantern.com/?p=298</guid>

					<description><![CDATA[<p>Learn to implement strlen from scratch in x86-64 assembly using YASM. We walk through building a null-terminated string length function with a while loop, proper register preservation, and ABI compliance, then use the length to print the string efficiently via sys_write.</p>
<p>The post <a href="https://www.NeuralLantern.com/implement-strlen-for-null-terminated-strings-in-x86-64-assembly-yasm/">Implement strlen for Null-Terminated Strings in x86-64 Assembly (YASM)</a> appeared first on <a href="https://www.NeuralLantern.com">NeuralLantern.com</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="Implement strlen for Null-Terminated Strings in x86-64 Assembly (YASM)" width="1380" height="776" src="https://www.youtube.com/embed/KQaIEBP6Qp4?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<p>Learn how to write your own strlen function in x86-64 assembly (YASM) that finds the length of a null-terminated string using a simple while loop.</p>



<p>We preserve the proper registers, follow the ABI, compute the length safely, and then use that length to print the full string efficiently with a single sys_write call.</p>



<p>Great for anyone studying low-level programming, operating systems, or wanting to understand C strings at the assembly level.</p>



<p>00:00:00 Introduction to implementing string length in assembly<br>00:00:25 What are null-terminated strings and why they exist<br>00:01:59 Pre-computing length vs using null terminators<br>00:02:53 How the null byte (0) actually works in memory<br>00:04:14 Naive approach: printing one character at a time<br>00:05:20 Goal: efficient printing using computed length<br>00:06:00 Program structure overview – two main functions<br>00:06:32 Data section: defining null-terminated strings<br>00:08:19 Additional strings for output (prefix, CRLF)<br>00:09:15 Text section start and global looper function<br>00:10:44 Preserving callee-saved registers (ABI prologue)<br>00:11:28 Calling print_null_terminated_string<br>00:12:43 Simple crlf printing helper function<br>00:13:10 print_null_terminated_string function signature<br>00:14:31 Prologue for print_null_terminated_string<br>00:15:44 Saving arguments and calling strlen<br>00:17:12 Using sys_write with computed length<br>00:18:19 string_length (strlen) function begins<br>00:19:20 Prologue and fake return value testing<br>00:20:44 Planning the while loop in C-like pseudocode<br>00:21:33 While loop initialization (pointer and counter)<br>00:24:23 Loop top: check for null terminator<br>00:26:23 Loop body: increment pointer and counter<br>00:27:37 Done label and return length in RAX<br>00:28:29 First successful run – full string printed<br>00:29:30 Adding direct strlen call and length printing<br>00:31:02 Final run showing both string and its length (54)<br>00:31:53 Summary – benefits of computed length printing<br>00:32:59 Improving loop structure (better jump pattern)<br>00:34:07 Final improved loop verification<br>00:35:03 Closing thoughts and thanks<br>00:35:27 Outro, call to subscribe, website mention</p>



<p>=-=-=-=-=-=-=-=-=</p>



<p>Thanks for watching!</p>



<p>Find us on other social media here:</p>



<ul class="wp-block-list">
<li>https://www.NeuralLantern.com/social</li>



<li>Twitter / X: https://x.com/NeuralLantern</li>



<li>Rumble: https://rumble.com/c/c-3696939</li>



<li>BitChute: https://www.bitchute.com/channel/pg1Pvv5dN4Gt</li>



<li>Daily Motion: https://www.dailymotion.com/neurallantern</li>



<li>Minds: https://www.minds.com/neurallantern/</li>



<li>Odysee: https://odysee.com/@NeuralLantern:5</li>
</ul>



<p>Please show your support!</p>



<ul class="wp-block-list">
<li>Buy me a coffee: https://ko-fi.com/neurallantern</li>



<li>Subscribe + Sharing on Social Media</li>



<li>Leave a comment or suggestion</li>



<li>Subscribe to Blog: https://www.NeuralLantern.com</li>



<li>Watching the main &#8220;pinned&#8221; video of this channel for offers and extras</li>
</ul>



<p>Hey there, in this video, I&#8217;m going to show you how to implement the function string length.</p>



<p>So you can find the length of a null terminated string in a Yasm x86-64 assembly program.</p>



<p>Although if you&#8217;re using a different assembly language or different architecture, this video</p>



<p>will probably still be useful to you because the concepts are going to be the same.</p>



<p>So what am I talking about?</p>



<p>I&#8217;m not going to be around here with this.</p>



<p>So in a previous video, I discussed null terminated strings.</p>



<p>I should also point out that a lot of basic knowledge is going to be skipped in this video</p>



<p>because I&#8217;ve explained it in other videos.</p>



<p>For example, if you don&#8217;t know how to compile, link, assemble, write a basic assembly program,</p>



<p>write a make file and so forth, then you should see my other videos first.</p>



<p>I&#8217;ve also already published a video about null terminated strings, but I&#8217;ll just do</p>



<p>it again here since that&#8217;s in the title of the video.</p>



<p>of the video so imagine you have a string and it&#8217;s hello right so under the hood uh the string is</p>



<p>probably a collection of characters on some level so we&#8217;ll just say this is h e uh l</p>



<p>l o right um when you&#8217;re printing</p>



<p>it&#8217;s unlikely that your entire memory stick is just done like it just you&#8217;re at the very end of your memory by the time that O hits</p>



<p>So that means you need some way of understanding when the string ends because if the memory is not over at that point</p>



<p>There could probably be some junk data at the end of it</p>



<p>You know like a bunch of other random letters or you can even imagine these as just you know</p>



<p>One byte that&#8217;s not one byte one byte numbers that just go on and on and on forever for the entirety of your RAM stick</p>



<p>of your RAM stick and you have to know how do we actually stop at the O. One thing that you can do</p>



<p>is just pre-compute the length of the string so we do that in assembly a lot before we know how</p>



<p>to scan for null terminators. We&#8217;ll say all right well that string is just five long so I&#8217;ll tell</p>



<p>the system I want you to print five characters starting at that memory location wherever the H is</p>



<p>and then the system knows okay I&#8217;ll just you know print the H-E-L-L-O and just stop after that.</p>



<p>null terminated strings are a lot more convenient because you don&#8217;t have to pre-compute the strings.</p>



<p>I mean, maybe your user entered a string.</p>



<p>Maybe you have a lot of strings or they change quite often.</p>



<p>Maybe you have like a multinational program that has tons of translations,</p>



<p>or I think multilingual is probably the better word for that.</p>



<p>But it can be a pain in the butt to constantly compute the length of strings in advance.</p>



<p>So with a null terminated string, you basically just say,</p>



<p>that I want to print and I&#8217;m just going to stick actually the number zero at the end of the string.</p>



<p>I&#8217;ll leave the junk data there just to let you know that there is some stuff happening in memory.</p>



<p>Notice how this zero, it is not actually the character that looks like a zero to a human.</p>



<p>That&#8217;s actually a totally different code than just zero. So you can imagine just an actual zero here.</p>



<p>You know, each of these characters that a human would look at has a number underneath it.</p>



<p>You know, this H is not really an H.</p>



<p>It&#8217;s just some number between 0 and 255 if we&#8217;re talking about ASCII.</p>



<p>The E is a different number and so forth.</p>



<p>So if we just put the literal number 0 in our data,</p>



<p>or if you want to quote this inside of a single quote,</p>



<p>you can do, I think, slash 0 just to let the compiler know</p>



<p>that you intend to have the number 0 there</p>



<p>instead of something that looks like the number 0, you know, the character.</p>



<p>you know the character but anyways the point is we just have to stick a zero at the end</p>



<p>of the string we call it a null terminator because zero is also you know an alias for null</p>



<p>whenever you have a null pointer or you assign null to a memory location or a pointer or something</p>



<p>you know it&#8217;s zero basically under the hood so a zero will terminate it&#8217;ll be like a token to let</p>



<p>us know that the string is finished and so since zero is also considered null we&#8217;ll say it&#8217;s a</p>



<p>we&#8217;ll say it&#8217;s a null terminator.</p>



<p>It&#8217;s a basic idea for null terminators.</p>



<p>Now the question is, how do we actually know when to stop?</p>



<p>Well, the first thing that you could do if you&#8217;re trying to write a program that is highly inefficient,</p>



<p>which I&#8217;ve definitely done before, is you could just print one character at a time.</p>



<p>You use a for loop.</p>



<p>You start at the very beginning of your string, you know, a pointer,</p>



<p>whatever the user gave you as like this is the first character.</p>



<p>We&#8217;ll just print that letter, and then we&#8217;ll go on to the next letter.</p>



<p>the next letter and before we print it actually before we print the first letter even before we</p>



<p>print this letter we&#8217;ll uh we&#8217;ll say is this like a regular character or is this a null terminator</p>



<p>is this a zero if it&#8217;s not a zero we print that character if it is a zero we terminate the loop</p>



<p>and then we go through every character one by one just you know checking and printing checking and</p>



<p>printing checking and printing unfortunately that&#8217;s kind of inefficient because every time</p>



<p>you call a print you know you&#8217;re you&#8217;re calling on a function you&#8217;re asking the system to do some</p>



<p>for you and it would be a lot better if we could just flush the whole string at</p>



<p>the same time but but know how long the string was that would increase our</p>



<p>efficiency so the program that we&#8217;re going to write together is basically</p>



<p>going to use our knowledge of a while loop which I&#8217;ve explained in other</p>



<p>videos already so see those other videos if you don&#8217;t know how to do while loops</p>



<p>in Yasm we&#8217;re going to use our knowledge of a while loop to sort of scan the</p>



<p>string real fast just you know kind of scan it and figure out how far into the</p>



<p>far into the string until we see a null terminator and use that to determine what is the length of</p>



<p>the string. At that point, we can use a system call in YASM, in assembly, to just say, I want you to</p>



<p>print this sequence of characters and here&#8217;s the length and then let the system worry about</p>



<p>efficiency. So with that said, let&#8217;s look at some code. Okay, it&#8217;s just going to be a simple while</p>



<p>loop. What we&#8217;re going to need to do is break this up into two parts. The first part is going to be</p>



<p>the first part is going to be a function called string length which you&#8217;ve probably already seen</p>



<p>in c if you program in c or c plus plus the second function is going to be called print null terminated</p>



<p>string which will just ask string length what the length of the string is first and then actually</p>



<p>print it with the system call so let me uh i guess let me start off with my data section here</p>



<p>to print I&#8217;m gonna copy paste that for my solution again this is not a not an</p>



<p>assembly basics video so if you don&#8217;t understand what I&#8217;m doing you should</p>



<p>watch my other videos first I&#8217;m assuming you know how to make a data section by</p>



<p>now we&#8217;ll put some C strings I&#8217;m just gonna make one null terminated string</p>



<p>actually I guess I&#8217;m making two but the focus of this program is just the first</p>



<p>one I&#8217;m calling it null terminated string and in assembly it&#8217;s pretty easy</p>



<p>you just make it a you know a character array just like a sequence of bytes with</p>



<p>a sequence of bytes with this DB meaning data bytes.</p>



<p>And I can just put a quoted string like this.</p>



<p>No problem.</p>



<p>As many characters as I want.</p>



<p>I can start injecting specific ASCII values if I wanted to</p>



<p>or byte values if I wanted to just by putting a comma</p>



<p>and then a number.</p>



<p>So I could do something like this.</p>



<p>I could do like, you know, 47, you know, 49, you know, 50, whatever.</p>



<p>If I knew the ASCII codes for the characters,</p>



<p>fortunately, I don&#8217;t need to.</p>



<p>normally into the double quoted area but then i need to be able to put a null terminator at the</p>



<p>end of my string because it&#8217;s not going to happen automatically so then i am going to do comma zero</p>



<p>and you&#8217;ll end up with something like this like if i guess if we look at the previous example real</p>



<p>fast i&#8217;ll call this a hello string just so that you see some similarity from what we just looked</p>



<p>a notepad thing would just be typing the word hello and then putting comma zero.</p>



<p>So it is now a null terminated string and it looks just like this inside of system memory.</p>



<p>Well, not just like that.</p>



<p>There would be numbers where the letters are, but you know, that&#8217;s basically what we have created.</p>



<p>And then of course there&#8217;s junk data afterwards, but we don&#8217;t really care about that.</p>



<p>You know, we&#8217;re just going to ignore it with the null terminator.</p>



<p>So I&#8217;m going to erase that since we&#8217;re not just going to print the word hello.</p>



<p>We have a null terminated string here and then after we print the null terminated string</p>



<p>I&#8217;m just going to print out what was the length of the string.</p>



<p>So this is a prefix string where it&#8217;s just, you know, it&#8217;s a prettier program.</p>



<p>The program is going to say the null terminated string&#8217;s length was something.</p>



<p>And then we&#8217;re going to use the null terminated string printer to print that also.</p>



<p>Convenient, right?</p>



<p>And then I&#8217;m going to actually print the number.</p>



<p>Then we have this down here, crlf, which is just printing a new line in the terminal.</p>



<p>That&#8217;s character code 13 and then 10 and then a null terminator so that we can use the null terminated string printer again.</p>



<p>And then we&#8217;re going to use system call code 1 to print a standard output right here.</p>



<p>If you don&#8217;t understand that, then see my other videos.</p>



<p>But let&#8217;s move on to the text section where all our instructions will go.</p>



<p>Okay, so now the instructions begin in our text section right here.</p>



<p>section.text and I&#8217;m using an external symbol this video is not about this</p>



<p>library here but basically I have a library that will help me print integers</p>



<p>you don&#8217;t need to worry about that you could imagine well I guess in your</p>



<p>example when you&#8217;re practicing if you don&#8217;t have this library you could just</p>



<p>not print the length of the string and just use it only and it all should still</p>



<p>work or you could hard code the thing that you&#8217;re printing if you really</p>



<p>wanted to. Okay, so I&#8217;m just going to continue on here. Now let&#8217;s do our entry point. So again,</p>



<p>this is not a video about hybrid programs. Just assume that there is another module in my program.</p>



<p>It&#8217;s a C++ module. It&#8217;s got the main function, you know, for the entry point for a hybrid program,</p>



<p>and it&#8217;ll just call on my looper function. So that&#8217;s why I&#8217;m marking a looper as global.</p>



<p>So my other module can call it. And well, it is a function that needs to return. So I&#8217;m going to</p>



<p>to return so i&#8217;m going to put ret at the end of it and you can see here i left myself a note saying</p>



<p>i&#8217;m going to use r12 to remember the length of the string so that i can print it back to the user</p>



<p>so that means i have to preserve r12 for the caller because the abi or the application binary</p>



<p>interface says that r12 is a callie saved register and if you don&#8217;t respect the abi</p>



<p>the abi is not going to respect you your program is going to end up crashing eventually</p>



<p>So I&#8217;m just going to do a push pop pair to preserve R12.</p>



<p>Oops, prologue and call that epilogue.</p>



<p>Okay. So we got a push pop pair. We got a return statement.</p>



<p>This program should probably do nothing so far. So let&#8217;s run it and see,</p>



<p>just make sure that it at least compiles.</p>



<p>So I&#8217;m going to say clear and make run running the program.</p>



<p>Hello from the driver. You don&#8217;t know that the driver has that.</p>



<p>that the driver has that. This is not a driver video. And then the driver regains control because</p>



<p>nothing happened inside of the assembly module. We just basically looper got called and then we</p>



<p>preserved R12 and then restored it and then we did nothing. Okay, so now let&#8217;s make a call to</p>



<p>print null terminated string. We have to make another function for this, but right now this is</p>



<p>just the call. So the name of the function that we&#8217;re going to write is called print null terminated</p>



<p>it it will call on the string length function to figure out how long the string is then it will use</p>



<p>a simple system call to print the whole string giving the length to the system call it also takes</p>



<p>two arguments the first argument is a pointer to the null terminated string so that&#8217;s just that</p>



<p>symbol we defined up above remember when you define variables up in the data section then</p>



<p>these symbols tend to be pointers so that symbol is a pointer to the h basically or just the memory</p>



<p>that h is sitting in ram then the second argument that it wants is uh is where we&#8217;re going to print</p>



<p>it so we&#8217;re just going to print it to standard output um which is just file descriptor number one</p>



<p>so again if you don&#8217;t understand arguments or you know file descriptors or function calls</p>



<p>see my other videos because i&#8217;ve explained those already anyway so we&#8217;re going to call</p>



<p>print null terminated string then we&#8217;re going to call on crlf which will just print a new line</p>



<p>So now maybe we should implement, well, let&#8217;s copy paste crlf so that I can implement the</p>



<p>other function a little bit more slowly.</p>



<p>What does crlf do?</p>



<p>It literally just asks the print null terminated string function to just print a crlf for us.</p>



<p>So it&#8217;s very, very simple.</p>



<p>Here&#8217;s the signature.</p>



<p>Nothing much to it.</p>



<p>Okay.</p>



<p>Now, a little bit more complicated is the print null terminated string function.</p>



<p>So in our looper, we&#8217;re going to print the null terminated string.</p>



<p>We have to have a function that actually does that.</p>



<p>So that&#8217;s going to be this one right here.</p>



<p>Here&#8217;s the signature that I&#8217;ve chosen for my print null terminated string function.</p>



<p>Basically, I want to receive a character pointer to the first character in the string that we&#8217;re going to print.</p>



<p>And then a file handle designating where we&#8217;re going to print it.</p>



<p>The reason I want to receive the file handle is so I could print a standard output or standard error.</p>



<p>or standard error, or I could print to a file,</p>



<p>like whatever I want to do.</p>



<p>You don&#8217;t have to have that in there, but it&#8217;s nice.</p>



<p>Anyway, so we have this function set up.</p>



<p>Notice how my notes that I left for myself</p>



<p>is that I&#8217;m gonna use R12</p>



<p>to remember the incoming C string pointer argument,</p>



<p>and I&#8217;m gonna use R13 to remember the file handle.</p>



<p>Remember, it&#8217;s probably not a good idea</p>



<p>to just let the incoming arguments</p>



<p>stay in their original registers,</p>



<p>original registers because those registers tend to get overwritten as you do system calls or</p>



<p>calls to any other function. So I&#8217;m just going to grab them real fast into R12 and R13. And then R14</p>



<p>is the string&#8217;s length, which I&#8217;m going to compute with a call to the function called string length.</p>



<p>So just three things to remember. And that&#8217;s it. So that means I&#8217;m going to have to preserve those</p>



<p>Okay, so we&#8217;re going to do a prologue to preserve those registers.</p>



<p>And then at the very end, we&#8217;re going to do an epilogue where we restore those registers.</p>



<p>Oh, I think I already overwrote my return statement from the previous function.</p>



<p>I think I did that in the last video and I was a little confused as to what was wrong.</p>



<p>So make sure you don&#8217;t accidentally overwrite or push down your return instructions.</p>



<p>Let me just double check here.</p>



<p>Looper&#8217;s got return.</p>



<p>Print and alternated string has got a return.</p>



<p>string has got a return.</p>



<p>CRLF has a return.</p>



<p>What the heck did I do?</p>



<p>Oh, I think I copy pasted in a bizarre place.</p>



<p>That&#8217;s probably what happened because the epilog for for print null terminated</p>



<p>string is like down in CRLF already.</p>



<p>That&#8217;s not good.</p>



<p>Okay, that would have been a crashing program.</p>



<p>Although sometimes if you omit the return statements, execution will just fall</p>



<p>through down to the next label and maybe your program will survive accidentally.</p>



<p>accidentally but for now it&#8217;s just crlf is supposed to be very simple it doesn&#8217;t preserve</p>



<p>any registers so we&#8217;ve got a prologue and an epilogue here notice how the push and pops are</p>



<p>in reverse order you want to know more about that see my other videos but now that we are preserving</p>



<p>the appropriate registers we can actually grab our incoming arguments so first thing i&#8217;m going to do</p>



<p>is i&#8217;m going to say r12 is going to be the first argument that i received and then r13 is going to</p>



<p>okay no problem then let&#8217;s rely on the string length function to compute the actual length of</p>



<p>the string i didn&#8217;t feel like having print null terminated string compute the length of the</p>



<p>string it&#8217;s a good idea especially in assembly or any language when you have multiple distinct</p>



<p>jobs happening within the same function you probably want to break that function up into</p>



<p>multiple functions just to reduce you know strain on your brain right cognitive load</p>



<p>So I&#8217;m going to use this function strlen string length to compute the length of the string.</p>



<p>It&#8217;s only going to take one argument and it&#8217;s going to take the pointer to the null terminated</p>



<p>string which is now in R12. It&#8217;s going to take that as its first argument so that&#8217;s why I&#8217;m loading</p>



<p>that up into RDI. When string length returns it&#8217;s going to give me the length of the string in the</p>



<p>RAX register which is the usual return register for integer or pointer return types. So I&#8217;m just</p>



<p>So I&#8217;m just going to save that in R14.</p>



<p>And that&#8217;s the usage of all those registers R12, 13, and 14.</p>



<p>We still have to implement string length.</p>



<p>Don&#8217;t worry.</p>



<p>Although if you were linking a hybrid program, you could probably just call</p>



<p>STRLEN in the C libraries and be fine.</p>



<p>But this is an assembly video.</p>



<p>We want to do everything in assembly if we can, or at least more of it.</p>



<p>So then finally, when we know what the strings length is, we can just use a</p>



<p>system call to actually print the string we&#8217;re going to say load up call code one to say you</p>



<p>know mr. system I want you to print a string and then r13 is going to be the file handle so we&#8217;re</p>



<p>going to basically say wherever the caller of print null terminated string said to print which</p>



<p>is probably going to be standard output we&#8217;ll just tell the system we want to print to the same place</p>



<p>and then r12 is a pointer to the c string so we just give that to the system call as well</p>



<p>system call wants to know how long the string is that&#8217;s r14 now now that we have used strlen</p>



<p>to determine the length of the string so not really that complicated of a function we just</p>



<p>kind of like grab some arguments preserve those registers and we ask another function to compute</p>



<p>the length of the string and then we actually just print it once we have the length this is still not</p>



<p>getting to the point where we&#8217;re going to use our while loop knowledge to compute the length so i</p>



<p>That&#8217;s probably all I need right now.</p>



<p>And I think we&#8217;re ready to use or to start the string length function.</p>



<p>Okay, so now let&#8217;s make another function called string length.</p>



<p>Hopefully I&#8217;ll paste in the right spot this time.</p>



<p>You&#8217;re cringing at home.</p>



<p>That just tells me that you care.</p>



<p>So the string length function, at least the version that I&#8217;m making right now,</p>



<p>just is going to take one argument.</p>



<p>It&#8217;s going to be a character pointer to the string that you want to compute.</p>



<p>It will expect that the string has a null terminator at the end.</p>



<p>the end if you accidentally didn&#8217;t put a null terminator at the end of the string then this</p>



<p>function definitely won&#8217;t work it&#8217;ll probably give you some huge number because it&#8217;ll go through ram</p>



<p>until it accidentally finds a zero um and then it&#8217;s going to return to you as its return value</p>



<p>and uh assigned a 64-bit integer actually this should be unsigned but i&#8217;m just putting long for</p>



<p>now um to indicate the length of the string okay inside the notes we&#8217;re going to use r12 and r13</p>



<p>So that means I should probably preserve those registers first before I do anything else.</p>



<p>So in the prolog, we&#8217;re going to push R12 and R13 so that we don&#8217;t break this program</p>



<p>for others.</p>



<p>And then we&#8217;re going to do an epilog.</p>



<p>Whoops.</p>



<p>Then we&#8217;re going to do an epilog to restore the registers.</p>



<p>And this is a function.</p>



<p>So it&#8217;s got to return to the caller.</p>



<p>If I didn&#8217;t put a return statement here, then execution is going to just go all the way</p>



<p>down to CRLF.</p>



<p>And this will be an infinite loop.</p>



<p>and this will be an infinite loop because crlf will end up calling null terminated string,</p>



<p>which we&#8217;ll then call string length, which will then fall through to crlf,</p>



<p>so the whole program won&#8217;t even work if we don&#8217;t have return.</p>



<p>And, you know, you don&#8217;t want to omit return statements anyways,</p>



<p>because that&#8217;s always a bad idea.</p>



<p>So now string length will just not do anything right now.</p>



<p>Maybe we could return a fake value for a second before we start implementing the loop.</p>



<p>the number five into RAX so that string length will always trick the caller into thinking that</p>



<p>the length of the string is five let&#8217;s see if that actually works we should get a portion</p>



<p>of the null terminated string unless I screwed something up</p>



<p>hello from the main driver notice how it just says hello here that&#8217;s kind of confusing let&#8217;s</p>



<p>let&#8217;s hard code the five to like a nine we should see more of that null terminated string</p>



<p>I sound when I wake up sometimes hello okay so let&#8217;s finish the str len function so again you</p>



<p>should know how while loops work if you don&#8217;t see my other videos but we&#8217;re going to use a while</p>



<p>loop to count the length of the string so we&#8217;re going to start with a little portion up here</p>



<p>think the string is and a running pointer so rdi is already supposed to come in as a pointer to the</p>



<p>string that we&#8217;re measuring so i&#8217;m going to save um the pointer into r12 so that we can have a</p>



<p>pointer that points to a character we&#8217;re going to use this as a running pointer so it&#8217;s going to like</p>



<p>sweep through the whole entire string until it hits a null terminator and then r13 is going to</p>



<p>keep track of uh how big we think the string is so when we first start we&#8217;re just looking at the</p>



<p>first start we&#8217;re just looking at the first letter and then we think the string has zero length.</p>



<p>So that&#8217;s the initialization part which will not be repeated as we continue looping. Now we&#8217;re</p>



<p>going to implement the top of the loop. I don&#8217;t know should I should I write this out as c code</p>



<p>for you? I don&#8217;t know if I should maybe let me do it. I didn&#8217;t prepare this so if it&#8217;s slow sorry</p>



<p>Maybe this is like a long strln, something like that.</p>



<p>And then we&#8217;ll do if my code is wrong or doesn&#8217;t compile, I&#8217;m so sorry.</p>



<p>I did not, I did not prepare this.</p>



<p>We&#8217;ll say character pointer s and then we&#8217;ll say, uh, maybe we can actually just leave</p>



<p>s alone because it&#8217;s coming in as an argument and in C plus plus you can just continue to</p>



<p>use that symbol.</p>



<p>It&#8217;s not going to get destroyed.</p>



<p>So imagine we&#8217;ve saved it already into R 12 and then we just keep using it.</p>



<p>using it so we&#8217;ll say while a let&#8217;s say a dereferencing of s is not equal to zero meaning</p>



<p>if we look at the value that the pointer is currently pointing to if we assume it&#8217;s just</p>



<p>pointing to one byte is we&#8217;ll keep going as long as that value is not a zero so that means</p>



<p>if the user called this function and gave us a pointer that was already looking at a zero</p>



<p>we would just return whoops we would just return that the length was zero so</p>



<p>that means I should probably keep track of the length here size type actually</p>



<p>long just to just to match the return signature long we&#8217;ll put size equals zero</p>



<p>and then at the very end we&#8217;ll just return the size and so again if the user</p>



<p>gave us a pointer that pointed to a zero already nothing would happen inside the</p>



<p>while loop we&#8217;d break through it right away and we would just return the number</p>



<p>the number zero that makes sense so then as long as it is not pointing at a zero</p>



<p>we&#8217;ll just increase what we think the size is and then we will increase the</p>



<p>pointer we can use s plus plus in C++ that&#8217;s just pointer arithmetic that&#8217;s</p>



<p>just going to tell the pointer to advance you know one memory location</p>



<p>further or whatever the data type is but in this case the data type is a</p>



<p>character so it really is going to be one memory location one byte so we&#8217;re</p>



<p>going to sweep through the string until we see a zero and then we stop and every time we see a</p>



<p>character that&#8217;s not a zero we increase our our measured length of the string by one and then</p>



<p>advance the pointer. So I haven&#8217;t tested this I don&#8217;t know if there&#8217;s an error in it but I hope</p>



<p>you get the basic idea of what we&#8217;re going to do. So that means up here you know this is the</p>



<p>initialization part that we were just talking about so we just set the running pointer to look</p>



<p>okay so then after we do that we are going to make the top of the while loop</p>



<p>so at the top of the while loop where we evaluate you know like right here this</p>



<p>is the top of the while loop it has to have its own label just like we explained</p>



<p>in the other videos and it is basically where we decide if we&#8217;re going to keep</p>



<p>looping or not are we going to jump into the body the loop or are we going to do</p>



<p>a long jump after the body to say that we&#8217;re done so the top of the loop is a</p>



<p>label. We compare the value that R12 is currently pointing at. We say that we only want to look at</p>



<p>one byte. We dereference R12 because remember R12 is supposed to be a pointer. You put the</p>



<p>brackets around it, it&#8217;s going to go to the memory location and then check what the value is that</p>



<p>the pointer is pointing to. That&#8217;s what dereferencing is, right? So we&#8217;re just going to</p>



<p>compare the byte that we&#8217;re looking at with a zero and we&#8217;ll say if it is equal to a zero,</p>



<p>jump to the done this is actually kind of a poor design pattern on my part usually we should jump</p>



<p>if it&#8217;s not equal into the body meaning we&#8217;ll always take a short jump into the body and then</p>



<p>execution will fall through on the next line to a long jump which has the ability to jump further</p>



<p>out of the body i&#8217;ve said in other videos that the conditional branch instructions they can only jump</p>



<p>about 128 bytes so if your if your loop body is too big then they won&#8217;t work but it&#8217;ll work for</p>



<p>But it&#8217;ll work for this example.</p>



<p>I don&#8217;t know, maybe if I have the gumption, I will fix up the loop for you if you want</p>



<p>me to after I copy paste my existing solution.</p>



<p>So for now we&#8217;re going to say, all right, I&#8217;m not going to do it.</p>



<p>I&#8217;m not going to do that.</p>



<p>Maybe in another video, if somebody requested, I might post another video in like five years.</p>



<p>Anyway, so we&#8217;re going to jump if it is a null terminator to the done label.</p>



<p>Otherwise we will fall through to the loop&#8217;s body where we&#8217;re just literally going to increase the pointer and also increase our idea of how big the string is.</p>



<p>So remember R12 is the pointer.</p>



<p>Integer arithmetic doesn&#8217;t, sorry, pointer arithmetic doesn&#8217;t really work here, but it accidentally works here because we&#8217;re looking at a byte array.</p>



<p>So if we just increase by one memory location, it will literally just increase by one memory location and we&#8217;ll be fine.</p>



<p>Just keep in mind that if you were sweeping through an array of, you know, quad words or some larger data type,</p>



<p>then just a simple ink wouldn&#8217;t actually work.</p>



<p>You&#8217;d have to increase by the appropriate number of bytes.</p>



<p>But hey, the number of bytes in one item is just one byte, so it&#8217;s easy.</p>



<p>So we&#8217;re making the pointer go forward by one on line 134 and then in line 135.</p>



<p>line 135 we&#8217;re increasing our idea of how big the string is and then we will unconditionally jump</p>



<p>to the top of our loop and so if you just kind of look at this what did i do i pasted that twice</p>



<p>oh god okay sorry guess i lost track of what i was doing so then we will unconditionally jump</p>



<p>to the top of the loop so basically you can imagine this loop is gonna it&#8217;s just gonna</p>



<p>continue forever just moving the pointer and increasing the counter and moving the pointer</p>



<p>finally when it sees a zero a null terminator then it actually breaks to</p>



<p>the done label and the done label is just doesn&#8217;t really do much it&#8217;s just a</p>



<p>label to get us out of the loop so the top of the loop says if we are done then</p>



<p>just jump to the done area notice how that skips over the the top jump and then</p>



<p>of course under that is going to be the epilog and then we can we can take the</p>



<p>we can take the return value and set that up now because at this point R13 should contain</p>



<p>the actual length of the string. So if we move that into RAX respecting the ABI for return values,</p>



<p>then the caller should be able to get the string length just at that point by itself.</p>



<p>So let&#8217;s see, that might actually be the whole entire program already. Let me</p>



<p>double check here. All right, let&#8217;s run it and see if it actually works.</p>



<p>and then do a make run.</p>



<p>What&#8217;s up with those asterisks?</p>



<p>Did I put that in there?</p>



<p>Oh, I wonder.</p>



<p>Okay.</p>



<p>So the driver comes in,</p>



<p>it calls on our function,</p>



<p>and the whole null terminated string gets printed out.</p>



<p>It says, hello, this is an example</p>



<p>of our null terminated string.</p>



<p>Notice how it printed the full length of the string,</p>



<p>not any less,</p>



<p>and it also didn&#8217;t print more than the length of the string,</p>



<p>i.e. junk data,</p>



<p>because it knew exactly how long the string was.</p>



<p>was and this is way better than printing one character at a time in terms of efficiency we</p>



<p>just pre-compute the length and then print exactly that length and then we&#8217;re done i think there is</p>



<p>one more thing i wanted to do here let me see up at the top yeah okay let me go back up to the top</p>



<p>of the program here so in the looper function we called on print null terminated string and we</p>



<p>didn&#8217;t do anything else so what i would like to do is just make an explicit call to string length</p>



<p>explicit call to string length inside of the lubr function just to get the length of the</p>



<p>null terminated string so we can just print it to the caller or print it to the user</p>



<p>and then I&#8217;m going to use my special library function here actually just just for your</p>



<p>information notice how I&#8217;m calling string length just like the the print null terminated string</p>



<p>function did and I&#8217;m just giving it as an argument a pointer to that null terminated string so then</p>



<p>So now I can just print r12</p>



<p>Well not yet, I&#8217;m gonna print a prefix if you look at the prefix here, it&#8217;s just</p>



<p>The null terminated strings length was and then I&#8217;ll print a number after that</p>



<p>You do it this way, you know your program is more pretty it&#8217;s more</p>



<p>It&#8217;s more nice to the user and so forth so I&#8217;m going to do this</p>



<p>we&#8217;re printing a nice prefix, a hard-coded string to the user to let them know that I&#8217;m about to</p>



<p>show them the length of the string. And then I use my external function that just prints a number to</p>



<p>the user. Again, this video is not about this library. You can use some other library if you</p>



<p>want to print something, or you can omit that part if you don&#8217;t have one set up yet. But</p>



<p>so I&#8217;m going to tell, I&#8217;m going to do first argument is R12, which was the length of the</p>



<p>I&#8217;m going to call this function and say I would like you to print r12 which is the length of the string so</p>



<p>After that we&#8217;ll print a new line to make things a little bit tidier and then I think this program is actually finished</p>



<p>Run it again now it says here&#8217;s the null terminated string and then on the next line it just says</p>



<p>The null terminated strings length was that was the prefix and then when I called my library</p>



<p>the number it says 54. so i don&#8217;t know was it 54? let&#8217;s just double check to make sure that it</p>



<p>actually was 54. 54 should not include the null terminator so i&#8217;m going to go 1 2 3 4 5 6 7 8 9 10</p>



<p>1 2 3 4 5 6 7 9 20 1 2 3 5 6 7 9 30 1 2 3 5 6 7 9 9 30 1 2 3 5 6 7 9 9 50 51 52 53 54 was it 54? i can&#8217;t even remember anymore.</p>



<p>So we have basically proved that this works.</p>



<p>We have leveraged our knowledge of while loops to implement a string length function, which</p>



<p>will let us have a printing function that is very smart.</p>



<p>So we don&#8217;t have to hard code string lengths up at the top anymore.</p>



<p>As long as we&#8217;re working with null terminated strings, everything will just work out now</p>



<p>with less variables or less defines.</p>



<p>Okay.</p>



<p>Let&#8217;s see.</p>



<p>I think that&#8217;s pretty much everything that I wanted to talk to you about.</p>



<p>I don&#8217;t know. Could I do,</p>



<p>could I do this easy, easily?</p>



<p>Loop top.</p>



<p>Okay. Yeah. I think I could probably do this reasonably.</p>



<p>So at this point,</p>



<p>you are satisfied that you understand how to implement this and you&#8217;re happy just cut the</p>



<p>video the rest of this video is going to be me sort of like improvising trying to figure out if</p>



<p>i can rearrange the logic in a fast enough time for a video uh just to show you that you know you</p>



<p>should you should probably write your loops a little bit better than i did so here we go but</p>



<p>this is this is just redundant stuff so we have our loop here and we have our initialization</p>



<p>The loop top, it should compare R12 to 0 and it should break the loop if it is a 0.</p>



<p>So that means I&#8217;m going to comment out this.</p>



<p>And I&#8217;m going to do jump not equal to 0 to the body.</p>



<p>And I just need to make a label for the body here.</p>



<p>So I&#8217;m going to say str lane loop bottom.</p>



<p>So there&#8217;s a label, which is the body.</p>



<p>Maybe I&#8217;ll do a comment here just to remind us that this is actually the body.</p>



<p>I guess I&#8217;ll do another comment right here.</p>



<p>So that&#8217;s the loop&#8217;s body.</p>



<p>So I&#8217;m going to say if R12 is not a null terminator, jump into the loop&#8217;s body.</p>



<p>Otherwise, we fall through to the next instruction,</p>



<p>and that will just be an unconditional jump to the done area.</p>



<p>Okay, and then when we&#8217;re inside the loop&#8217;s body, we&#8217;ll jump back up to the top.</p>



<p>I don&#8217;t know why I thought this was going to be hard.</p>



<p>Let me run this to make sure I didn&#8217;t break the program.</p>



<p>Yeah, it still works.</p>



<p>Okay.</p>



<p>I guess I overestimated the difficulty there.</p>



<p>The point being, the body is a lot closer to the top of the loop.</p>



<p>So that should be the thing that does a conditional branch.</p>



<p>You should conditionally branch to the body because it&#8217;s a shorter jump and therefore</p>



<p>much less likely to be out of bounds of that 128 conditional jump bite restriction.</p>



<p>And then when we fall through to the next line, because we did not do that jump,</p>



<p>because we did not do that jump then we&#8217;ll do an unconditional jump to the done area and you know</p>



<p>our loop is small so it didn&#8217;t really matter the first time we did this but um again imagine your</p>



<p>loop is huge that you definitely want an unconditional jump that goes to the done area</p>



<p>at that point and that&#8217;s also what we&#8217;re doing an unconditional jump to the top here when we get to</p>



<p>the end of the body so when you&#8217;re jumping large uh you know spans you want to use unconditional</p>



<p>Alright, so I guess that&#8217;s it.</p>



<p>I&#8217;m going to erase maybe this comment.</p>



<p>Well, I&#8217;ll leave that in there just for posterity.</p>



<p>And now I will officially say that I hope you had a good time watching this video.</p>



<p>I hope you learned a little bit of stuff and I hope you had a little bit of fun.</p>



<p>I will see you in the next video.</p>



<p>I&#8217;m going to go play some video games.</p>



<p>Maybe I&#8217;m going to eat some soup first.</p>



<p>Hey everybody.</p>



<p>Hey everybody, thanks for watching this video again from the bottom of my heart. I really</p>



<p>appreciate it. I do hope you did learn something and have some fun. If you could do me a please,</p>



<p>a small little favor, could you please subscribe and follow this channel or these videos or</p>



<p>whatever it is you do on the current social media website that you&#8217;re looking at right now.</p>



<p>It would really mean the world to me and it&#8217;ll help make more videos and grow this community.</p>



<p>So we&#8217;ll be able to do more videos, longer videos, better videos, or just I&#8217;ll be able to keep making</p>



<p>to keep making videos in general. So please do me a kindness and subscribe. You know, sometimes</p>



<p>I&#8217;m sleeping in the middle of the night and I just wake up because I know somebody subscribed</p>



<p>or followed. It just wakes me up and I get filled with joy. That&#8217;s exactly what happens every single</p>



<p>time. So you could do it as a nice favor to me or you could troll me if you want to just wake me up</p>



<p>in the middle of the night, just subscribe and then I&#8217;ll just wake up. I promise that&#8217;s what</p>



<p>will happen. Also, if you look at the middle of the screen right now, you should see a QR code,</p>



<p>you should see a QR code which you can scan in order to go to the website which I think is also</p>



<p>named somewhere at the bottom of this video and it&#8217;ll take you to my main website where you can</p>



<p>just kind of like see all the videos I published and the services and tutorials and things that I</p>



<p>offer and all that good stuff and if you have a suggestion for clarifications or errata or just</p>



<p>future videos that you want to see please leave a comment or if you just want to say hey what&#8217;s up</p>



<p>what&#8217;s going on? You know, just send me a comment, whatever. I also wake up for those in the middle</p>



<p>of the night. I get, I wake up in a cold sweat and I&#8217;m like, it would really, it would really mean</p>



<p>the world to me. I would really appreciate it. So again, thank you so much for watching this video</p>



<p>and enjoy the cool music as, as I fade into the darkness, which is coming for us all.</p>



<p>Thank you.</p>
<p>The post <a href="https://www.NeuralLantern.com/implement-strlen-for-null-terminated-strings-in-x86-64-assembly-yasm/">Implement strlen for Null-Terminated Strings in x86-64 Assembly (YASM)</a> appeared first on <a href="https://www.NeuralLantern.com">NeuralLantern.com</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.NeuralLantern.com/implement-strlen-for-null-terminated-strings-in-x86-64-assembly-yasm/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Mastering x86-64 Assembly: A Beginner&#8217;s Guide to CPU Registers</title>
		<link>https://www.NeuralLantern.com/mastering-x86-64-assembly-a-beginners-guide-to-cpu-registers/</link>
					<comments>https://www.NeuralLantern.com/mastering-x86-64-assembly-a-beginners-guide-to-cpu-registers/#respond</comments>
		
		<dc:creator><![CDATA[mike]]></dc:creator>
		<pubDate>Sun, 27 Jul 2025 00:12:09 +0000</pubDate>
				<category><![CDATA[Assembly Language]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[Computer Science]]></category>
		<category><![CDATA[Videos]]></category>
		<category><![CDATA[ABI]]></category>
		<category><![CDATA[assembly language]]></category>
		<category><![CDATA[assembly programming]]></category>
		<category><![CDATA[callee saved registers]]></category>
		<category><![CDATA[coding optimization]]></category>
		<category><![CDATA[computer architecture]]></category>
		<category><![CDATA[CPU registers]]></category>
		<category><![CDATA[general purpose registers]]></category>
		<category><![CDATA[low-level programming]]></category>
		<category><![CDATA[programming tutorial]]></category>
		<category><![CDATA[RAX register]]></category>
		<category><![CDATA[RBX register]]></category>
		<category><![CDATA[stack pointer]]></category>
		<category><![CDATA[x86-64 assembly]]></category>
		<category><![CDATA[Yasm assembly]]></category>
		<guid isPermaLink="false">https://www.NeuralLantern.com/?p=190</guid>

					<description><![CDATA[<p>Learn x86-64 assembly with this beginner’s guide to CPU registers. Master RAX, RBX, ABI rules, and optimize code. Perfect for low-level programming enthusiasts.</p>
<p>The post <a href="https://www.NeuralLantern.com/mastering-x86-64-assembly-a-beginners-guide-to-cpu-registers/">Mastering x86-64 Assembly: A Beginner&#8217;s Guide to CPU Registers</a> appeared first on <a href="https://www.NeuralLantern.com">NeuralLantern.com</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="Mastering x86-64 Assembly: A Beginner&#039;s Guide to CPU Registers" width="1380" height="776" src="https://www.youtube.com/embed/jPysL_y4rRA?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<p>Ready to dive into x86-64 assembly? This beginner-friendly video breaks down CPU registers like RAX, RBX, and more in Yasm assembly. Learn how to use general-purpose registers, respect the ABI to avoid debugging nightmares, and optimize code by minimizing RAM hits. We’ll cover callee-saved registers, function arguments, and why you shouldn’t mess with the stack pointer. Perfect for coders looking to master low-level programming. Grab the free book mentioned and subscribe for more assembly tips! #AssemblyProgramming #x86</p>



<p>Introduction to Registers 00:00:00<br>x86-64 Yasm Assembly 00:00:04<br>Recommended Book 00:00:09<br>Move Instruction Example 00:01:04<br>64-bit Registers Overview 00:01:52<br>General Purpose Registers 00:02:24<br>Two&#8217;s Complement for Integers 00:03:37<br>Floating Point Registers Introduction 00:03:54<br>ABI Importance 00:04:55<br>Function Return Values 00:08:01<br>C++ to Assembly Translation 00:08:43<br>Avoiding System RAM 00:11:45<br>Optimizing with Registers 00:13:04<br>Callee Saved Registers 00:14:16<br>Preserving Registers with Push/Pop 00:16:40<br>Stack and Local Variables 00:22:00<br>Function Arguments in Registers 00:25:12<br>Stack Pointer and Base Pointer 00:31:29<br>Instruction Pointer (RIP) 00:36:30<br>Temporary Registers (R10, R11) 00:36:49<br>Accessing 32-bit Register Portions 00:38:29<br>Floating Point Registers Details 00:42:53<br>Conclusion and Call to Subscribe 00:45:35</p>



<p>Thanks for watching!</p>



<p>Find us on other social media here:</p>



<ul class="wp-block-list">
<li>https://www.NeuralLantern.com/social</li>
</ul>



<p>Please help support us!</p>



<ul class="wp-block-list">
<li>Subscribing + Sharing on Social Media</li>



<li>Leaving a comment or suggestion</li>



<li>Subscribing to our Blog</li>



<li>Watching the main &#8220;pinned&#8221; video of this channel for offers and extras</li>
</ul>



<p>Hello there.</p>



<p>Let&#8217;s talk about registers in assembly.</p>



<p>More specifically, x8664 Yasm assembly.</p>



<p>Okay, so first off, check out this book.</p>



<p>It&#8217;s a wonderful book.</p>



<p>The author is a genius.</p>



<p>It&#8217;s called x8664 assembly language programming with Ubuntu.</p>



<p>It&#8217;s free.</p>



<p>website and you know grab your copy it&#8217;s wonderful it&#8217;s released under a copy left license</p>



<p>author&#8217;s a genius whenever i&#8217;m trying to remember things about cpu registers for assembly</p>



<p>i always go to this section i say callie saved i search for callie saved i already had it there</p>



<p>callie saved and it ends up being section 12.8.2 register usage so before we do that let me just</p>



<p>that let me just give you a little quick example so you kind of know what I&#8217;m</p>



<p>talking about here hopefully everybody&#8217;s seen this instruction by now this is a</p>



<p>move instruction in Yasm x86 64 assembly it just moves data from one place to</p>



<p>another it takes two operands so you know we have like operand one and</p>



<p>operand two basically operand one is the destination operand so we could put</p>



<p>destination there if we wanted to operand two is the source we could put</p>



<p>that actually won&#8217;t, you know, compile or assemble,</p>



<p>but I&#8217;m just saying that&#8217;s what those positions are for.</p>



<p>So here&#8217;s an example of a register receiving the value 10.</p>



<p>We use the move instruction and we say,</p>



<p>we would like to move something into the REX register.</p>



<p>We would like to move the value 10 into the REX register.</p>



<p>And there you have it. There&#8217;s a move instruction. Okay.</p>



<p>So REX is a register.</p>



<p>that it is a 64-bit register in our 64-bit CPUs every single register or</p>



<p>sorry every single general purpose register and the plot registers they</p>



<p>have 64 bits available for us to use 64 bits like you know ones and zeros it&#8217;s</p>



<p>like a very very very big number a long time ago we had 32 bit registers and so</p>



<p>these are like you know twice as mathematically robust or whatever you</p>



<p>allows the registers to address, you know, the 64 bit memory addressing space,</p>



<p>which helps us go beyond four gigabytes of RAM in our modern computers,</p>



<p>helps us go far beyond what we can even achieve right now.</p>



<p>So we have a register called RAX and there&#8217;s a list of other registers on this</p>



<p>page here. So basically, you know,</p>



<p>we have the RAX register and the RBX register and the RCX register and so</p>



<p>forth. I have a hard time remembering all these names,</p>



<p>remembering all these names so I go to this book when I forget but otherwise</p>



<p>you know you can kind of think of like ABCD and then just surround them with</p>



<p>RNX you know our kind of for register and X for extra big maybe so we&#8217;ve got</p>



<p>the RAX RBX RCX and RDX registers and then we have a bunch of other ones</p>



<p>through R15 but first before we do that let me just emphasize that these are</p>



<p>general purpose registers to be used for integers or data you can put</p>



<p>characters in there for strings you can put just like you know whatever data you</p>



<p>want inside the machine we use twos complement to represent integers so it&#8217;s</p>



<p>it&#8217;s fine the instructions that you will do for addition and other mathematical</p>



<p>but don&#8217;t put floating point numbers in these registers because the computer the</p>



<p>system the machine won&#8217;t know how to operate on that data the thing is</p>



<p>integers are stored as twos complement I&#8217;m going to talk about that more in</p>



<p>another video and floats are stored in something called I triple E seven five</p>



<p>four standard which is just like a crazy different way of storing floating point</p>



<p>numbers that makes more sense for floating point numbers but because the</p>



<p>differently in the machine you can&#8217;t really use normal instructions like you</p>



<p>can&#8217;t add two floats together the same with the same instruction that you would</p>



<p>add two integers together you would have to use special floating point registers</p>



<p>and special floating point instructions I&#8217;ll talk about floats at the end of</p>



<p>this video I hope but basically just keep in mind these are general purpose</p>



<p>registers to be used for integers in data only okay so what am I talking</p>



<p>Okay, so what am I talking about?</p>



<p>What are we seeing here on the side here?</p>



<p>Why does it say return value?</p>



<p>What is going on with Kali saved and fourth argument and third argument and so forth?</p>



<p>So there&#8217;s a standard that you&#8217;re supposed to use when you program.</p>



<p>You can get yourself into a lot of hot water or you can dramatically increase your debugging</p>



<p>time if you don&#8217;t do this.</p>



<p>standard called the ABI which I think is short for application binary interface but basically I just</p>



<p>like to say the ABI respect the ABI there&#8217;s a plan that people came up with that says this is how you</p>



<p>should use these registers don&#8217;t use them in a different way and that way if everybody is writing</p>



<p>you know modules and they&#8217;re all going to interact together like I write a module you write a module</p>



<p>the abi then it&#8217;s it&#8217;s pretty much guaranteed that we can we can expect certain things like</p>



<p>our registers won&#8217;t become corrupted after a function call or that we&#8217;re not going to corrupt</p>



<p>someone else&#8217;s uh function or you know whatever right so you can also use this to benefit yourself</p>



<p>even if you&#8217;re the only person who is writing your code and you&#8217;re not calling on anyone else&#8217;s</p>



<p>function um then you know like how are you going to remember like what was i using this register</p>



<p>Was I supposed to save that one?</p>



<p>Was I supposed to preserve it?</p>



<p>How was I going to return data from that function?</p>



<p>Was I going to use this register or the other register?</p>



<p>It&#8217;s hard to remember what you,</p>



<p>what you yourself even did like a month ago.</p>



<p>So if you respect this plan,</p>



<p>then your functions will work not only</p>



<p>with other people&#8217;s functions,</p>



<p>but with your own functions from a month ago.</p>



<p>The other thing too, is we have system calls, right?</p>



<p>So you have like a system call.</p>



<p>Let&#8217;s say we want to move something into REX.</p>



<p>something into REX, maybe I want to exit the system or something.</p>



<p>Just forget about this.</p>



<p>This is not a system call video.</p>



<p>Suppose I want to do a system call, right?</p>



<p>The system call itself is also going to respect the ABI.</p>



<p>So if you start calling other</p>



<p>services in the system call instruction, like if you want to open a file,</p>



<p>close a file, read a file, write a file, whatever.</p>



<p>If you don&#8217;t respect the ABI and the system call is respecting the ABI,</p>



<p>might have some of your data corrupted so it&#8217;s a really really good idea to respect the abi</p>



<p>in fact think about it this way what if uh what if you wrote a bunch of functions for a long long</p>



<p>time and then like a year later you couldn&#8217;t you couldn&#8217;t remember what you were doing you know</p>



<p>last year oh what was the return register uh and it costs you a bunch of extra time debugging</p>



<p>eventually you&#8217;ll probably decide to write your write your own standard okay from now on i&#8217;m always</p>



<p>going to use this register for return values and i&#8217;m going to use this register for the first</p>



<p>and i&#8217;m going to use this register for the first argument and i&#8217;m going to write you probably</p>



<p>come up with a plan right that&#8217;s basically the abi the abi covers more than just how to use</p>



<p>registers but um register usage is covered in the abi so why would you put yourself through</p>



<p>a bunch of heartache and then eventually come up with your own plan when you could have just</p>



<p>been following the correct plan in the first place right so everybody should respect the abi</p>



<p>I wanted to talk next about the return value.</p>



<p>Okay, so let me write up a little function here.</p>



<p>Let me just say that we have a C++ function.</p>



<p>And we&#8217;ll just say it&#8217;s like void f.</p>



<p>And we&#8217;ll say it calls on g.</p>



<p>And then we&#8217;ll have another function called g.</p>



<p>And actually, maybe it&#8217;s not void.</p>



<p>Maybe it actually does return a long.</p>



<p>returns the number five or something. Okay.</p>



<p>Hopefully you&#8217;ve seen some kind of a higher level language before like C++</p>



<p>so that you can understand what&#8217;s going on here.</p>



<p>We&#8217;re just making two functions and one is calling the other.</p>



<p>And the second one is just returning a value to the first one.</p>



<p>So in assembly, the equivalent of this would be,</p>



<p>let&#8217;s make a label with the name of the function and then a little colon,</p>



<p>and then just put a return instruction at the end of it. Wham,</p>



<p>it, wham, you&#8217;ve got a function. It&#8217;s not going to work very well, but you do have a function at</p>



<p>this point. So F, uh, I&#8217;m going to try to copy the C++, uh, function. So it&#8217;s a really good idea.</p>



<p>Whenever you&#8217;re writing a function in assembly, try to imagine what the prototype would be for</p>



<p>C++ and just put it as a comment at the top. So I know how the F function is going to behave in</p>



<p>my assembly module because I put a comment up there just kind of reminding me what the prototype</p>



<p>for C++. It doesn&#8217;t really do anything. It just sort of runs. So that&#8217;s okay. And then I&#8217;ll make</p>



<p>another function down here. I&#8217;ll do the long G again in a comment, and then I&#8217;ll do the actual</p>



<p>assembly version. I&#8217;ll say G colon, and then I&#8217;ll return. So just by putting that comment up,</p>



<p>I kind of can remind myself now that the G function is supposed to return some kind of a value.</p>



<p>up here, you know, do how about let&#8217;s say, I don&#8217;t want to start adding a bunch of local</p>



<p>variables right now.</p>



<p>Pretend that we&#8217;re going to print the return value of the call to G somehow we&#8217;re going</p>



<p>to use C out or whatever.</p>



<p>We&#8217;re going to send it to a variable, whatever.</p>



<p>I&#8217;m just going to try to keep the assembly as simple as possible.</p>



<p>But anyway, the point is G returns something.</p>



<p>you know, a value in your assembly function.</p>



<p>Well, remember that higher level languages,</p>



<p>part of why they&#8217;re so awesome</p>



<p>is they do a lot of extra work for us under the hood</p>



<p>and they actually provide illusions to us</p>



<p>that make programming easier.</p>



<p>For example, there are no functions</p>



<p>going on inside the actual machine.</p>



<p>I mean, I guess from a certain point of view there are,</p>



<p>but basically the machine is just sort of like moving data</p>



<p>and jumping to instructions</p>



<p>and jumping back from somewhere.</p>



<p>And, you know, it&#8217;s just sort of like jumping around</p>



<p>and executing instructions.</p>



<p>and executing instructions there&#8217;s no actual function it&#8217;s so it&#8217;s like if you want to pretend</p>



<p>that you have a function in assembly well there is a return instruction that will help you jump</p>



<p>back to wherever you came from most recently but we have to we have to implement more is what i&#8217;m</p>



<p>saying so how do we return a value in an assembly function we just have to load up the return value</p>



<p>it as return value that just means we have to load rax up with something so for example we wanted to</p>



<p>return the number five so i&#8217;m just going to load it up with the number five and then return</p>



<p>now we&#8217;ve pretty much translated a c plus plus function into uh an assembly function i mean</p>



<p>that&#8217;s really what&#8217;s happening under the hood when you compile your c plus plus program</p>



<p>it&#8217;s um it&#8217;s just you know translating all the c plus plus into assembly</p>



<p>Another thing that I should probably point out is that you should use registers as often as possible</p>



<p>and you should try your best not to touch memory.</p>



<p>Of course at some point you have to touch memory when you want to save your final result or send</p>



<p>it off somewhere or whatever but you know imagine that you have an assembly function and you&#8217;re</p>



<p>doing lots and lots of calculations you&#8217;re performing an algorithm or something your</p>



<p>program will be so much more efficient by like a factor of a hundred or probably more if you don&#8217;t</p>



<p>if you don&#8217;t hit system ram because every time you hit system ram like a global variable or the</p>



<p>stack or something then um your cpu you know typically in the uncashed uh scenario your cpu</p>



<p>has to go talk to the system bus on your motherboard and then you know send a message</p>



<p>to system ram and then wait for the system ram to figure out what it&#8217;s doing and then get a response</p>



<p>back so when your program is executing on the cpu you can encounter a stall which is like your</p>



<p>like a hundred clock cycles or more like it&#8217;s a long time at least in the most basic case</p>



<p>and how do you avoid that just use registers only when you&#8217;re doing lots of calculations the</p>



<p>registers are built into the cpu they&#8217;re part of the cpu&#8217;s hardware so they are lightning fast</p>



<p>compared to system ram or your disk or whatever</p>



<p>i probably say this a lot but you know part of the reason you would even want to code an assembly</p>



<p>Maybe you have a big program that does a lot of stuff and eventually you profile the program</p>



<p>and you realize, Hey, this one part of the program is really slow because it gets called</p>



<p>constantly and it&#8217;s not super efficient.</p>



<p>That might be a good use case for writing a hybrid program where you have multiple modules.</p>



<p>Some of your modules are in a higher level language and some of your modules are in assembly.</p>



<p>So you take your most important function that slows down your program that gets called all</p>



<p>like a big loop or something and you rewrite it to assembly so that you can</p>



<p>have more control over how often you touch system RAM to try to make the</p>



<p>whole thing more efficient and you know reduce the number of instructions and</p>



<p>just like whatever and you can improve the product of the efficiency of your</p>



<p>program so anyway you want to try to avoid hitting system RAM your registers</p>



<p>are built in the CPU there&#8217;s 64 bits that gives us 64 bits of address space</p>



<p>can reach you know back in the day we had 32 bit systems that means you could only have a memory</p>



<p>stick that was about four gigabytes so now we can go much further so um yeah that&#8217;s what&#8217;s going on</p>



<p>with our registers on the cpu back to the return value okay so we have return value here goes into</p>



<p>the rax register and then the next thing here is it&#8217;s saying that the rbx register is something</p>



<p>remember we said that uh we have to respect the abi right like you have to respect this convention</p>



<p>uh because if you don&#8217;t you&#8217;re going to cost yourself debug time and your</p>



<p>functions probably won&#8217;t be interoperable interoperable with other people&#8217;s functions</p>



<p>or the system call uh instruction well so one of the things about the abi is some of the registers</p>



<p>are designated as the function that is being called has to be the thing that saves the register&#8217;s</p>



<p>registers value so that it doesn&#8217;t corrupt for the caller. Imagine this if I had a function</p>



<p>called f I&#8217;m going to do like f and g here suppose the function f is going to move something into</p>



<p>let&#8217;s say r12 or actually let&#8217;s do rbx move the value 10 into rbx and then it&#8217;ll call g for some</p>



<p>reason maybe g doesn&#8217;t take any arguments maybe g is just kind of doing stuff let&#8217;s just say that</p>



<p>g just moves a different value into rbx so the thing is when the call comes back like after we</p>



<p>get to this next line let&#8217;s say we&#8217;re going to do something with do something do something with</p>



<p>rbx by the time we get to this line dude can i get the line numbers on this oh yeah i forgot okay</p>



<p>so by the time we get to line seven uh the register rbx is ruined these registers are not</p>



<p>local variables they&#8217;re not like uh you know tied to any scope or function call these registers are</p>



<p>just basically global variables that are sitting on the cpu for lightning fast performance but that</p>



<p>means the rbx i use inside of f is the same rbx i use inside of g so that means if g messes up the</p>



<p>value of rbx and then if f calls g then f now has a bad value for rbx this is a broken program</p>



<p>broken program because we did not respect the ABI.</p>



<p>The ABI says that RBX is callee saved,</p>



<p>which means if I use RBX in the G,</p>



<p>then I have to preserve the value so that by the time I return,</p>



<p>the value is the same as it was when the call first came in.</p>



<p>So how do we do that?</p>



<p>We&#8217;ll do that with a push pop pair.</p>



<p>I&#8217;ll probably make more videos in the future about pushing and popping,</p>



<p>but I&#8217;m going to try to keep it simple for now.</p>



<p>We just say, let&#8217;s push RBX onto the stack.</p>



<p>at the beginning and then we&#8217;ll pop it off the stack at the very end.</p>



<p>This basically means we&#8217;re going to take the value of RBX.</p>



<p>We&#8217;re going to send it onto the stack.</p>



<p>So, so yeah, we are hitting system RAM.</p>



<p>It&#8217;s a little slower at that point.</p>



<p>The ABI will save us a little time for the other registers.</p>



<p>I&#8217;ll try to explain that in a second, but basically we&#8217;re preserving the value here</p>



<p>with push and then we&#8217;re popping it back off.</p>



<p>So we&#8217;re restoring it.</p>



<p>So that means even though we ruined the value at line 14, when F does its line</p>



<p>When F does its line 7, it&#8217;s going to have the correct value of RBX.</p>



<p>It&#8217;s going to have the value 10.</p>



<p>The book and I like to call this the prologue, just meaning this is a little section of code</p>



<p>where we&#8217;re going to set things up.</p>



<p>We&#8217;re going to start getting ready to do more instructions.</p>



<p>And then this at the bottom is going to be called the epilogue.</p>



<p>This is just like the finale.</p>



<p>We&#8217;re like, we&#8217;re kind of cleaning up.</p>



<p>We&#8217;re finishing up right before we return.</p>



<p>If you wanted to return a value from G, then you could put, you know, the move inside of</p>



<p>RAX somewhere else.</p>



<p>Like you could put it like below the epilogue or just above the epilogue.</p>



<p>It&#8217;s fine.</p>



<p>As long as you&#8217;re sure that RAX is not getting trampled upon.</p>



<p>So it&#8217;s important to note also that if I do a, let&#8217;s say a system call right after that,</p>



<p>let&#8217;s say I call G and then I do a system call with, you know, like, you know, some</p>



<p>you know some other number as the call code i want to open a file i want to close a file</p>



<p>i want to read or write a file whatever i want to ask the system to do something for me the</p>



<p>system is also going to respect the abi which means i&#8217;m guaranteed that rbx is not modified</p>



<p>when the system call comes back if if the system call you know if the syscall instruction didn&#8217;t</p>



<p>respect the abi then my rbx could be ruined i&#8217;d have to do a bunch of stuff to preserve it so this</p>



<p>some of these registers let me go down a little bit here like this R10 the</p>



<p>temporary register and also the RDI if you decided to use that in the body of</p>



<p>your program which you&#8217;re allowed to these are not designated as callee saved</p>



<p>which means system call could actually ruin the value of those registers so</p>



<p>suppose for the sake of argument I really decided that I needed to use I</p>



<p>10 because that&#8217;s marked as a temporary I&#8217;ll put a value in our 10 and then I&#8217;ll say you know</p>



<p>do something</p>



<p>With our 10 I&#8217;m sorry our 10</p>



<p>Then that means by the time I&#8217;m done with my call to G</p>



<p>I should assume that our 10 is ruined because even though you&#8217;re you can see right here that that G doesn&#8217;t actually do anything</p>



<p>To our 10 we should assume that we have to respect the ABI which means the other function could have ruined it</p>



<p>Ruined it. This is especially true if you call someone else&#8217;s module or system call or whatever same thing for the system call</p>



<p>so if I call system call</p>



<p>and I use</p>



<p>R10 at some point before and then after then I have to assume R10 is destroyed by the time I get back in system call</p>



<p>So that&#8217;s no good</p>



<p>The cure to that when we&#8217;re talking about a temporary or something that is not designated as callee saved is that the caller has to save</p>



<p>hit a system RAM just to make a call.</p>



<p>Anything that we think we need when we&#8217;re finished.</p>



<p>So I&#8217;m going to do a push.</p>



<p>This is not the only way to do it, but I&#8217;m going to do a push R10 here.</p>



<p>And then afterwards, I&#8217;m going to do pop R10.</p>



<p>So that sucks.</p>



<p>And then I have to do the same thing for the system call.</p>



<p>I can go push R10 and then pop R10.</p>



<p>And of course, if you were clever, you probably would, you know, put the call to G inside</p>



<p>of that system call push pop pair.</p>



<p>So you could have one less push pop pair.</p>



<p>push pop pair but I&#8217;m just saying there&#8217;s no guarantee r10 is going to survive so you always</p>



<p>have to preserve it if you ever want to use it again so this is like another way that the abi</p>



<p>kind of can help you save time notice how here in the uh in the g function which I probably should</p>



<p>have prototyped let me just say it looks like to me it&#8217;s a void and it doesn&#8217;t take any arguments</p>



<p>to prototype your functions in comments.</p>



<p>Maybe let me do the same thing to F up here.</p>



<p>So F looks like it&#8217;s not returning anything and it&#8217;s not taking anything.</p>



<p>Okay. Whoops.</p>



<p>Those are C++ comments that would not compile.</p>



<p>All right. So notice how I&#8217;m using RBX.</p>



<p>So I decided to preserve RBX, but there&#8217;s also other registers that are marked as</p>



<p>marked as Kali saved like R12 through 15 and RBP and whatever,</p>



<p>but I&#8217;m not preserving those.</p>



<p>The reason I don&#8217;t have to preserve those is because I&#8217;m not using them.</p>



<p>So the, uh, the, uh, the ABI can save you a little time here.</p>



<p>Like for example, I&#8217;m preserving R10 because I&#8217;m supposed to assume that I,</p>



<p>that I, that they could be destroyed by the time the function comes back.</p>



<p>What if instead of using R10, I used R12.</p>



<p>have to surround any calls with a push pop pair because I can trust that whoever is going to</p>



<p>modify R12 will preserve it for me. But then notice down here G is not actually using R12.</p>



<p>So G doesn&#8217;t even do push pop on R12. So we save hits to memory. We don&#8217;t even have to touch memory</p>



<p>to preserve R12 because the ABI is helping us sort of stay a little bit more efficient.</p>



<p>So this is great, right? F is a broken function at this point though, because I&#8217;m using</p>



<p>at this point though because I&#8217;m using two registers that are callee saved I</p>



<p>can&#8217;t assume that whoever called F is gonna know that I&#8217;m modifying RBX and</p>



<p>R12 so I should do a prolog and an epilog up here I&#8217;m gonna say push RBX</p>



<p>and then I&#8217;m gonna push R12 and then down here at the bottom I&#8217;m gonna do an</p>



<p>epilog epilog and I&#8217;m gonna pop RBX and I&#8217;m gonna pop R12</p>



<p>but I&#8217;ve done something wrong.</p>



<p>The thing is, I&#8217;m not going to talk about the stack too much in this video,</p>



<p>but the stack is a particular type of data structure</p>



<p>that will return to you data in a reverse order than you sent into it.</p>



<p>This is great for helping us keep track of function calls and return addresses,</p>



<p>as I&#8217;ll probably try to explain in this video.</p>



<p>But basically, the data comes out backwards.</p>



<p>The data comes out backwards. So if I do it like this</p>



<p>Then actually by the time the return statement instruction gets executed</p>



<p>RBX will have the value that was intended for R12 and R12 will have the value that was intended for RBX</p>



<p>It&#8217;ll be backwards. So you have to do your push pops in the reverse order to notice how</p>



<p>It&#8217;s kind of like a shell that goes outwards. It&#8217;s like R12 is first on the inside and then RBX is next on the outside</p>



<p>That&#8217;s just what you have to do to preserve everything.</p>



<p>So the F function works now.</p>



<p>The G function, I think it works now.</p>



<p>We have a prologue and epilogue.</p>



<p>Okay, so we talked about the ABI.</p>



<p>We talked about calls.</p>



<p>We talked about the registers.</p>



<p>Talked about callee saved.</p>



<p>We talked about the fact that we don&#8217;t have to save the other ones.</p>



<p>I think I can talk about…</p>



<p>um so uh one thing that i should make sure to mention is that these are general purpose registers</p>



<p>they&#8217;re to be used for integers integer data or like characters or just like regular data</p>



<p>they use certain instructions that are not to be used with floating point data so you actually</p>



<p>should not store floating point numbers inside of your general purpose registers you should only</p>



<p>store floating points in special registers which i&#8217;ll talk about at the end of this video</p>



<p>So keep that in mind.</p>



<p>Floating point numbers are stored differently in the system.</p>



<p>They&#8217;re stored with a scheme called IEEE 754 floating point.</p>



<p>So like the numbers wouldn&#8217;t make sense.</p>



<p>Integers and floats are stored differently.</p>



<p>So the hardware is wired differently to operate on two different types of data.</p>



<p>So anyway, I just want to say that this is only for integers and general purpose data.</p>



<p>So now let&#8217;s look at the other types of registers.</p>



<p>rc x and rd x and rsi and rdi are designated as arguments first second third and fourth</p>



<p>okay so let me uh let me write like a quick c plus function here and this is going to be uh let&#8217;s</p>



<p>say we have like a function that returns some value we&#8217;ll call it uh we&#8217;ll call it f and we&#8217;ll</p>



<p>say that f takes in some arguments let&#8217;s say that it takes in three arguments um again uh</p>



<p>integers right now because we&#8217;re only using integer registers.</p>



<p>We can&#8217;t use floating point arguments or return values.</p>



<p>Just keep that in mind.</p>



<p>So I&#8217;m just going to do like three arguments long A and B and C.</p>



<p>OK, so we can take in three arguments and maybe we&#8217;re just going to return,</p>



<p>you know, a plus B plus C.</p>



<p>OK, simple C++ function.</p>



<p>Let&#8217;s do this in assembly.</p>



<p>We&#8217;ll make a label and we&#8217;ll do a little comment that just reminds us.</p>



<p>of sorry of the</p>



<p>Function that we&#8217;re trying to implement we stick a little return instruction at the end of it so that</p>



<p>it will jump back to the caller and</p>



<p>then we&#8217;ll say</p>



<p>Well when the caller of this function</p>



<p>Called us and gave us a and B and C. How do we get a and B and C?</p>



<p>Well a is the first integer argument, so it&#8217;s just going to be the RDI register</p>



<p>So we&#8217;ll literally just use a move instruction</p>



<p>just use a move instruction.</p>



<p>Let&#8217;s say we want to, for whatever reason, use the R12 register</p>



<p>and we&#8217;ll do something with it later.</p>



<p>We&#8217;ll print it, we&#8217;ll save it, we&#8217;ll do whatever.</p>



<p>Let&#8217;s just grab the incoming argument.</p>



<p>So we&#8217;ll just grab RDI.</p>



<p>So I&#8217;m going to put a little comment up above here, you know, grab</p>



<p>a and do something</p>



<p>with it and I&#8217;ll just write down here more instructions just to just to denote</p>



<p>Just to denote that we&#8217;re doing something with the a value, but I&#8217;m not going to write it down here because I don&#8217;t want this to get huge.</p>



<p>So we&#8217;ll do the same thing with the b.</p>



<p>Maybe I should remember that programming is case sensitive.</p>



<p>We&#8217;ll do something with the b.</p>



<p>It&#8217;s not RDI.</p>



<p>It&#8217;s the second argument.</p>



<p>So that&#8217;s actually RSI.</p>



<p>And then we&#8217;ll do something else.</p>



<p>We could have used R13 or other registers if we wanted to.</p>



<p>I&#8217;m just showing you how to grab incoming arguments.</p>



<p>So then we&#8217;ll grab the c and do something with it also.</p>



<p>C and do something with it also it&#8217;s not going to be RDI it&#8217;s going to be RDX and you can do this</p>



<p>up to like I think six arguments let me just double check here yeah so like R9 ends up being</p>



<p>the sixth argument and if you want more than that then the caller will have to put stuff on the stack</p>



<p>and in fact if you if you kind of like understand what&#8217;s happening here let me just do like a main</p>



<p>Let&#8217;s say we do cout whatever f returns.</p>



<p>You know, this is like a typical function call, right?</p>



<p>So we&#8217;ll call f.</p>



<p>f will jump in there.</p>



<p>It&#8217;ll jump into its body.</p>



<p>It&#8217;ll do some sort of a manipulation with the incoming arguments.</p>



<p>It&#8217;ll return a final value.</p>



<p>Then that final value gets printed out.</p>



<p>So what&#8217;s 5 plus 6 plus 7?</p>



<p>That&#8217;s 11 plus 7.</p>



<p>What is that, like 18?</p>



<p>I&#8217;m bad at math.</p>



<p>So let&#8217;s just say that&#8217;s 18 gets printed.</p>



<p>So what happens is, um, we return, Oh, I forgot to return.</p>



<p>I&#8217;m going to say compute the, uh,</p>



<p>compute the sum of the things.</p>



<p>Uh, and I&#8217;ll just say like block cause I don&#8217;t want to put a bunch of addition</p>



<p>instructions here. Uh, and we&#8217;ll just like store in, uh,</p>



<p>in R13, let&#8217;s say. So then when we have finally computed our result, I&#8217;ll just move R13 into the</p>



<p>return value. And what I&#8217;m really trying to say here is if you imagine a function that behaves</p>



<p>this way in C++, then what I&#8217;ve written down below is really what&#8217;s actually happening in</p>



<p>assembly. Your compiler compiles the code down to assembly language first, and then it assembles it</p>



<p>down to machine code. So really this is what&#8217;s happening under the hood. It&#8217;s not like a special</p>



<p>under the hood it&#8217;s not like a special trick when you call a function in C++</p>



<p>literally the A B and C have been loaded up just before the the jump</p>



<p>instruction to go to that you know line 9 they&#8217;ve been loaded up with the</p>



<p>appropriate values so that&#8217;s part of like you know the magic of what higher</p>



<p>level languages give us it&#8217;s just makes things a little bit easier okay so I&#8217;ve</p>



<p>If I had only used RDI and RSI and RDX, those are not designated as callee saved.</p>



<p>So I wouldn&#8217;t have had to preserve those, but because I chose to use R12 and R13, I</p>



<p>have to preserve those for the caller, even if the caller is not going to use them.</p>



<p>So I&#8217;m going to do, I&#8217;m going to do push R12 and I&#8217;m going to do push R13.</p>



<p>And then at the bottom, let me do like a prologue here.</p>



<p>is kind of helpful because it kind of helps you remember like, oh, did I forget the prologue?</p>



<p>Did I forget the epilogue? They got a match. And then I guess the fact that you can see the words</p>



<p>prologue and epilogue also helps remind you that everything is supposed to be in reverse order</p>



<p>in the epilogue. So again, notice how R13 is on the inside and R12 is on the outside</p>



<p>of the push pop pair. So now my program is good. And we&#8217;ve, you know, successfully translated</p>



<p>We&#8217;ve, you know, successfully translated a nice function call there.</p>



<p>And we&#8217;ve done a bunch of nonsense in the middle that I&#8217;m not writing down at this point.</p>



<p>We are respecting the ABI.</p>



<p>So if somebody else uses our function in their module, then they can be pretty confident</p>



<p>that we&#8217;re not going to ruin their registers and so forth.</p>



<p>We talked about the return value.</p>



<p>We talked about that these general purpose registers are not for floats.</p>



<p>We talked about pushes and pops.</p>



<p>and pops. We&#8217;ve talked about function arguments,</p>



<p>which right now we can only do integer arguments and return values.</p>



<p>We&#8217;ve talked about, uh, well, he talked about the stack a little bit.</p>



<p>So let me, let me just point out that, um,</p>



<p>suppose you have a function. I just want to mention this briefly.</p>



<p>Suppose you have a function F let&#8217;s say it&#8217;s, it&#8217;s void.</p>



<p>So it doesn&#8217;t return anything and it has an integer a equals five.</p>



<p>I think the reason that I wanted to do this is to show you how dangerous it is to mess</p>



<p>with the wrong register like the stack register.</p>



<p>So suppose we have two variables and then we&#8217;ll do something with a and b.</p>



<p>So now suppose we have two threads.</p>



<p>We have an execution thread one and an execution thread two.</p>



<p>If you&#8217;re not familiar with threads, that just basically means your computer is literally</p>



<p>executing your function or sorry, it&#8217;s executing twice at the exact same time.</p>



<p>Maybe not the exact same time if you only have a single core on your CPU, but you could</p>



<p>imagine that that&#8217;s possible, especially if you have many cores, that&#8217;s an operating systems</p>



<p>video.</p>



<p>But basically pretend that we have an execution thread.</p>



<p>So it&#8217;s like going through your program, executing one instruction at a time.</p>



<p>Then you launch another execution thread that also executes your program one instruction</p>



<p>at a time.</p>



<p>at a time so at some point it&#8217;s possible that um thread one and thread two could be executing f</p>



<p>at the exact same time right so i&#8217;m not going to talk too much about this because this is not an</p>



<p>os video but basically this could create a race condition where thread one and thread two kind</p>



<p>of step on each other&#8217;s toes and they both try to modify the value of a uh at the wrong time and</p>



<p>because the other thread modified it.</p>



<p>So this is why local variables in a function actually live on the stack.</p>



<p>A and B are not global variables.</p>



<p>They&#8217;re actually temporary local variables that are sitting on the stack.</p>



<p>And the way the stack works, I&#8217;m not going to talk about it too much in this video,</p>



<p>is that, well, every function kind of has its own area of the stack.</p>



<p>So when the function comes in, on the stack sits the return address</p>



<p>return address so that the function knows where to jump back to when it returns and any local</p>



<p>variable that the function makes. So if you think about it, when thread one calls F, we actually</p>



<p>end up with a different version of A and a different version of B. We could imagine them</p>



<p>as being, you know, A sub one and B sub one. But when thread two comes in and, you know,</p>



<p>creates those local variables, we can imagine that we get two different versions of A and B also.</p>



<p>of a and b also so this is how the computer prevents multiple threads from stepping on each</p>



<p>other&#8217;s toes if you&#8217;re using local variables local variables are just local to the function</p>



<p>this also helps if a function calls itself a bunch of times maybe one call or another might want to</p>



<p>see a different version of a or b and it would be just incredibly difficult to keep track of that</p>



<p>if you were using globals but when you use locals well they&#8217;re just basically different variables</p>



<p>trying to lead up to is the stack is pretty important if you corrupt the</p>



<p>stack then you probably are going to crash the entire program you might make</p>



<p>it so that a function doesn&#8217;t know where to return from like when you do the</p>



<p>return statement it might jump to some other part of the code that doesn&#8217;t even</p>



<p>make sense and then everything crashes or you might mess up some data in a local</p>



<p>variable like if you mess up if you mess up the stack you might be messing up the</p>



<p>that the caller is depending on and so then the caller continues to execute and</p>



<p>it sees the wrong value and it just crashes or you might even mess up your</p>



<p>own local variables so don&#8217;t miss with the stack the reason I&#8217;m saying that now</p>



<p>is because this very this register right here the RBP sorry that&#8217;s not it the</p>



<p>RSP register that&#8217;s the stack pointer eventually you can learn how to</p>



<p>manipulate the stack pointer in order to create your own local variables that&#8217;s</p>



<p>variables that&#8217;s okay once you know what you&#8217;re doing but unless you know exactly what you&#8217;re</p>



<p>doing you probably shouldn&#8217;t touch the stack pointer especially you shouldn&#8217;t mess with it</p>



<p>right before you call a function or right before you return from your own function be very careful</p>



<p>with that the rbp uh register is similarly dangerous uh it won&#8217;t like automatically destroy</p>



<p>your program but it is uh it&#8217;s usually i mean it&#8217;s quite often used as sort of like a bookmark for</p>



<p>mark for where the stack pointer was pointing in other modules and other</p>



<p>functions.</p>



<p>So if you fail to preserve the base pointer,</p>



<p>the RBP and then you returned from your function,</p>



<p>then you might have actually messed up the stack pointer for the caller or some</p>



<p>other caller somewhere in like the ancestry of your call graph.</p>



<p>So be very careful. I mean,</p>



<p>I guess all callee preserved variables or registers you should be very careful,</p>



<p>careful about, but these are like kind of the two worst ones to forget about.</p>



<p>first ones to forget about.</p>



<p>There&#8217;s also another register that is not listed on this page called the</p>



<p>instruction pointer. It&#8217;s RIP.</p>



<p>It basically is a register that holds</p>



<p>the memory location of the next instruction to be executed.</p>



<p>So if you modify that, then you just told your program to go execute</p>



<p>in some random crazy place and probably everything is going to crash.</p>



<p>R10 and R11.</p>



<p>I can&#8217;t remember already if I explain this, but I&#8217;ll just say it again.</p>



<p>But I&#8217;ll just say it again, R10 and R11 are just temporary registers.</p>



<p>You don&#8217;t have to preserve them.</p>



<p>But the callee, if you call another function, they don&#8217;t have to preserve the registers either,</p>



<p>which means it can be really fast to use R10 and R12 if you&#8217;re kind of like already running out of registers.</p>



<p>If you don&#8217;t have to make a function call anywhere, so you know no one is going to ruin your R10 and R11,</p>



<p>then you can also use R10 and R11 to sort of like, you know,</p>



<p>reduce your hits to system RAM to speed up your program.</p>



<p>So R10 and R11, they should probably be used last.</p>



<p>R12, 13, 14, 15, I usually use those first.</p>



<p>Once I start running out of those, Kali saved.</p>



<p>Then I&#8217;ll start eating into the arguments.</p>



<p>I&#8217;ll say, you know, I&#8217;m going to start using RBX</p>



<p>and then I&#8217;m going to use RDI and RSI and whatever.</p>



<p>It&#8217;s okay if you use, you know, the argument registers.</p>



<p>as long as you&#8217;ve already done something with your incoming arguments or you don&#8217;t have any.</p>



<p>So just keep that in mind.</p>



<p>You&#8217;re allowed to use them.</p>



<p>I mean, this is all just a standard.</p>



<p>As long as you obey what the rule is, then you&#8217;ll be all right.</p>



<p>The rule is you got to callee save those.</p>



<p>The rule is that one&#8217;s just temporary.</p>



<p>The rule is this one&#8217;s an argument and so forth.</p>



<p>Okay.</p>



<p>locals and how we use these registers. Let me try to just show you one more</p>



<p>thing real fast. So I said before that the size of the REX register is 64 bits</p>



<p>because it takes up the whole available register bits in the CPU but there are</p>



<p>other versions of this register that we could use. What if you only wanted to use</p>



<p>32 bits in your register? What if you wanted to pack like two different 32</p>



<p>32-bit numbers in the same 64-bit register.</p>



<p>You could do that.</p>



<p>There are also older modules and instructions</p>



<p>that will operate only on 32-bits.</p>



<p>So how do you reference only 32-bits of a register?</p>



<p>Well, if I search for, oh shoot, what was it?</p>



<p>Is it EDI?</p>



<p>No, no.</p>



<p>Shoot.</p>



<p>It&#8217;s in here somewhere.</p>



<p>This is like a good lesson in actually preparing before you record a video.</p>



<p>So I&#8217;m going to do architecture overview, CPU registers.</p>



<p>Oh, it was at the beginning of this section.</p>



<p>I always skip down to 2.4, 12 point something, and I should have gone to 2.3.1.1.</p>



<p>So obviously I&#8217;m not going to remember all of this, but basically notice at the top,</p>



<p>we have the REX register, all 64 bits of it.</p>



<p>But if you wanted to access the lowest six, sorry, the lowest 32 bits, then in your code,</p>



<p>instead of putting REX, you put EAX.</p>



<p>So for example, you know, move REX, whoops, REX, let&#8217;s say the number five, but over</p>



<p>here we&#8217;re going to move EAX, the number five.</p>



<p>five uh here it&#8217;s going to set the whole 64 bits to just like a bunch of zeros and then there&#8217;s</p>



<p>going to be a few bits that help represent five the lowest bits so it&#8217;s going to erase like the</p>



<p>whole thing all 64 bits but if you use the eax instruction then only the lowest 32 bits will</p>



<p>actually be modified which means whatever data you had in the higher 60 the higher 32 bits of the</p>



<p>of the register itself they&#8217;re just going to stay there it&#8217;s going to be considered</p>



<p>point so sometimes if you&#8217;re going to work with something that&#8217;s going to be using only 32 bits</p>



<p>of your register you better make sure that the other bits are uh are cleared out if you intend</p>



<p>to use rax right after that and and vice versa so keep in mind that we have other forms of the same</p>



<p>register a designation but just to let the cpu know that we only want to touch 32 bits worth we</p>



<p>And this, this kind of table covers all of the registers,</p>



<p>REX, RBX, RCX, and so forth.</p>



<p>I think it doesn&#8217;t cover the instruction pointer</p>



<p>and something else in there, but you know, most of them.</p>



<p>However, you know, for my purposes,</p>



<p>I usually just use 64 bits</p>



<p>because I&#8217;m not like super advanced</p>



<p>unless I have to divide or do something.</p>



<p>Okay, so that&#8217;s the last thing I wanted to mention</p>



<p>about the general purpose registers.</p>



<p>Let&#8217;s see.</p>



<p>Callie saved.</p>



<p>So the not sure if I said this before already, but basically the.</p>



<p>So just to emphasize the, uh, the RBP register is the base pointer register.</p>



<p>You&#8217;re probably going to mess up, uh, the caller because the caller often uses RBP as</p>



<p>a bookmark for the stack pointer.</p>



<p>mark for the stack pointer you definitely don&#8217;t want to mess with a stack pointer unless you</p>



<p>actually know what you&#8217;re doing in order to create local variables um there&#8217;s another variable</p>



<p>another register in here called rip which is the instruction pointer register so if you</p>



<p>if you mess that one up then the program is going to start executing in some crazy place that doesn&#8217;t</p>



<p>even make sense okay so now that we&#8217;ve talked about general purpose registers by the way i</p>



<p>called special purpose registers, not general purpose.</p>



<p>General purpose is like RAX, RBX, all these ones that you can just randomly use as long</p>



<p>as you respect the ABI.</p>



<p>But the base pointer and the stack pointer, those are kind of special.</p>



<p>And the RIP, the instruction pointer, that&#8217;s a special register.</p>



<p>You shouldn&#8217;t mess with those unless you really know what you&#8217;re doing or you&#8217;ll get yourself</p>



<p>in trouble.</p>



<p>But now that we&#8217;ve talked about those, let&#8217;s talk about the floating point registers just</p>



<p>real fast.</p>



<p>about using floats until a lot later but basically</p>



<p>i at least want to mention that we do have registers that will work with floating point</p>



<p>operations let me see there we go okay so it&#8217;s 18.2 floating point registers um essentially</p>



<p>we use xmm0 through xmm13 for floating point numbers there&#8217;s not going to be any</p>



<p>not going to be any crazy letters like RDI, RSI that you have to memorize. You can just use zero</p>



<p>through 15 and it&#8217;s totally fine. When you want to return a floating point number from a function,</p>



<p>you will load up XMM0 as the return value. You won&#8217;t even touch RAX. The arguments are the same.</p>



<p>They&#8217;re just kind of ordered. It&#8217;s like the first argument is going to be XMM0. The second argument</p>



<p>is going to be XMM1 and so forth all the way up to XMM15. If you need more than 15 arguments,</p>



<p>some sorcery with the stack or with some kind of system like the global variable or something</p>



<p>and also for floating point registers we use different instructions so what I really want</p>



<p>you to know because this is mostly about the regular registers is that if you have floating</p>



<p>point numbers and you want to multiply them or do some other operation on them the normal</p>



<p>instructions for regular registers won&#8217;t actually work you&#8217;ll have to look up a different set of</p>



<p>and i&#8217;m going to do this in another video some other time uh if you want to move uh data with</p>



<p>a floating point register you can&#8217;t just use the regular move instruction you got to use either</p>



<p>move ss or move sd um and and both operands have to be floats or actually i think the one on the</p>



<p>right can be memory but um move ss basically means a single piece of data single precision</p>



<p>So you can move like multiple pieces of data at a time.</p>



<p>I&#8217;m not going to really cover that.</p>



<p>Um, but you can move single precision floating points, which means there are 32 bit floating</p>



<p>points or you can move double precision floating points, which means they&#8217;re a full 64 bit</p>



<p>floating point number.</p>



<p>There&#8217;s also bigger registers, but I&#8217;m not going to talk about that.</p>



<p>Yeah.</p>



<p>Well, yeah.</p>



<p>Later processors 256.</p>



<p>I think mine has that, but I&#8217;m not going to talk about that.</p>



<p>I think mine are like YMM or something.</p>



<p>So yeah, with that, those are the basics of registers and some stuff to keep in mind.</p>



<p>In future videos, I&#8217;m going to talk more in depth about making functions and calling functions</p>



<p>and all that stuff, respecting the ABI.</p>



<p>But for now, here is your primer.</p>



<p>I hope it was useful on CPU registers.</p>



<p>Thank you for watching this video.</p>



<p>I&#8217;ll see you in the future.</p>



<p>I hope you had a little bit of fun and you learned a little bit of stuff.</p>



<p>hey everybody thanks for watching this video again from the bottom of my heart I really</p>



<p>appreciate it I do hope you did learn something and have some fun if you could do me a please a</p>



<p>small little favor could you please subscribe and follow this channel or these videos or whatever</p>



<p>it is you do on the current social media website that you&#8217;re looking at right now it would really</p>



<p>mean the world to me and it&#8217;ll help make more videos and grow this community so we&#8217;ll be able</p>



<p>longer videos, better videos, or just I&#8217;ll be able to keep making videos in general.</p>



<p>So please do me a kindness and subscribe. You know sometimes I&#8217;m sleeping in the</p>



<p>middle of the night and I just wake up because I know somebody subscribed or</p>



<p>followed. It just wakes me up and I get filled with joy. That&#8217;s exactly what</p>



<p>happens every single time. So you could do it as a nice favor to me or you could</p>



<p>you could troll me if you want to just wake me up in the middle of the night.</p>



<p>Just subscribe and then I&#8217;ll just wake up. I promise that&#8217;s what will happen.</p>



<p>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</p>



<p>Which I think is also named somewhere at the bottom of this video</p>



<p>and it&#8217;ll take you to my main website where you can just kind of like see all the videos I published and</p>



<p>services and tutorials and things that I offer and all that good stuff and</p>



<p>If you have a suggestion for</p>



<p>Clarifications or errata or just future videos that you want to see</p>



<p>please leave a comment or if you just want to say, Hey, what&#8217;s up, what&#8217;s going on? You know,</p>



<p>just send me a comment, whatever. I also wake up for those in the middle of the night. I get,</p>



<p>I wake up in a cold sweat and I&#8217;m like, it would really, it really mean the world to me. I would</p>



<p>really appreciate it. So again, thank you so much for watching this video and, um, enjoy the cool</p>



<p>music as, as I fade into the darkness, which is coming for us all.</p>



<p>Thank you.</p>
<p>The post <a href="https://www.NeuralLantern.com/mastering-x86-64-assembly-a-beginners-guide-to-cpu-registers/">Mastering x86-64 Assembly: A Beginner&#8217;s Guide to CPU Registers</a> appeared first on <a href="https://www.NeuralLantern.com">NeuralLantern.com</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.NeuralLantern.com/mastering-x86-64-assembly-a-beginners-guide-to-cpu-registers/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
