Mastering x86-64 YASM Assembly: Functions Made Simple

Mastering x86-64 YASM Assembly: Functions Made Simple

Get hands-on with x86-64 YASM assembly in this in-depth tutorial on writing functions! Perfect for beginners and seasoned coders, we cover the basics of function creation, calling conventions, argument handling, and return values. Learn to avoid crashes, respect the ABI, and use prologue/epilogue for clean code. From printing messages to returning integers, see practical examples and tips to simplify your assembly programs. Subscribe for more low-level programming tutorials and take your skills to the next level!

Introduction to Functions 00:00:00
Makefile Overview 00:00:19
Assembly Program Setup 00:02:01
Data Section Definitions 00:02:08
Text Section and Entry Point 00:03:02
Basic Assembly Program Demo 00:03:38
Return Codes Explained 00:04:30
Function Concepts Introduced 00:06:10
Creating a Simple Function 00:07:04
Function Call vs Jump 00:08:00
Adding Return Statement 00:09:06
Moving Print Logic to Function 00:09:48
Benefits of Functions 00:10:01
Calling Function Multiple Times 00:11:58
Creating Print Function with Arguments 00:14:00
Handling Function Arguments 00:15:45
Respecting the ABI 00:17:16
Prologue and Epilogue 00:23:15
Stack Operations 00:24:34
Calling Print Function 00:25:25
Avoiding Recursive Loop 00:34:17
Modifying Print Function to Print Line 00:35:21
Adding CRLF Function 00:30:13
Printing Multiple Messages 00:37:00
Returning Integer Values 00:37:48
Preserving Registers in Entry Point 00:41:50
Final Program Demo 00:43:24
Conclusion and Call to Subscribe 00:45:16

Thanks for watching!

Find us on other social media here:

  • https://www.NeuralLantern.com/social

Please help support us!

  • Subscribing + Sharing on Social Media
  • Leaving a comment or suggestion
  • Subscribing to our Blog
  • Watching the main “pinned” video of this channel for offers and extras

Hey there! Let’s talk about functions in x8664 Yasm Assembly.

I’m just going to give you the basics of how to write a function.

So let’s get started here. First thing I want to show you is just a makefile.

This is not a makefile video, so you don’t have to worry about it too much.

I just have it up because I need it for this demo.

If you’re interested in makefiles, that would be a really, really good thing.

thing i’ll probably make videos in the future about them but for now we’ll just say you hopefully have

a script or method already set up that allows you to compile or assemble assembly programs

so i’m just going to skim through it real fast if you’re interested you can kind of study it

but basically i have like a little define here that allows me to print out a message that looks

nice and then i define the repo path as the current path and i take the absolute path of that

This is where the real work happens.

I have Yasm flags because I’m using the Yasm assembler.

I’m going to be assembling to x86 64.

I like to out.

I like to convert all of my warnings to errors to make sure that I don’t write sloppy code

export debug symbols and export debug symbols for the linking stage to the name of my executable

is going to be called a main.

have set up and well I can just do make run or make debug as a little shortcut

to run it in GDB if you don’t know GDB don’t worry that’s going to happen in a

future video and make clean which just cleans the build area I like a clean

build area and then this is the main command here we’re going to be using LD

to do our linking because this is going to be a pure assembly program instead of

a hybrid program which would require GCC or something else and then here’s my

And then here’s my program main ASM is going to get compiled down to main.o and

That’s it for the make pile

Okay, so for the main assembly program I have some stuff written up already here, but I think I’m going to modify it for this video

For starters, we have our data section which hopefully you understand already

I’m just going to define a bunch of stuff in the data section like I’m going to define

The system call code to write a string so I can print a message pretty easily

so I can print a message pretty easily the system call code to actually exit the program

remember when you’re writing a pure assembly program that has start as an entry point

you need to be you know you’re responsible for exiting the program so the system call code is

60 there and then I’m going to say exiting for success is a zero that’s kind of a standard thing

and then I’m going to make two file descriptors for the standard input it’s going to be zero and

the standard output it’s going to be one actually I don’t think we need that for this video we just

We just need standard output, but not standard input.

And then I’m just going to make two strings.

That’s not my name, but I like those names.

And then the BSS section.

Actually, I’m going to get rid of that

because we don’t really need that for this video.

And then I have a text section, which is where all the code is.

We’re going to begin our entry point.

If you are writing a pure assembly program

and this is your entry point module,

make a function called underscore start.

It’s not actually technically going to be a function because it won’t return anywhere.

It’ll actually just call the system exit service.

And then I mark start as global so that the operating system can go into it,

can call it from the outside.

And then all I’m doing right now is I’m printing a hello.

So far, this is not really a demo of functions.

This is just like a very basic pure assembly program.

All it’s going to do is it’s going to enter.

going to print the hello message and then down here it’s going to do a system call to exit the

program with zero for success so let’s just see what that looks like real fast I’m going to do

make run and then make run you can see the first line it just kind of prints and then the second

line that’s make sort of echoing the command that I’m issuing it’s just going to assemble the main

dot asm into a main dot o and then it’s letting me know that if there are any warnings it will

It will refuse to compile.

And then I use the LD linker to link the main executable.

And then I actually run the executable.

So only below this line that I have highlighted right now

is gonna be the actual program.

So you can see all it really did was just,

you know, print the message and then exit.

Just, you know, a little note here.

I’ve probably said this in other videos,

but the return code zero is kind of a standard

to indicate success for programs,

which is very useful if you want programs to automate other programs.

If I change the system, let’s see what is it, exit success.

If I just change that variable to a 3 so that I will exit with a return code of 3 instead of 0,

then the operating system, or actually bash, since we’re in a terminal emulator,

should consider the program to have exited in error.

So you can see now it’s like, hey, hey, hey, the makefile system,

oh not bash, the makefile system is like that program exited with code 3,

three something went wrong and normally if you don’t add any extra stuff into your make file it’ll

just refuse to continue at that point well so i’m just going to change it back to a zero and make

sure that it still works and then we’ll get on to actually writing functions so i’m going to go clear

and make run so it’s a little bit faster for me to run this repeatedly you can see actually the

first time that i did that um the make file recompiled notice how it recompiled um and

and relinked because I changed that source code.

This is not a make file video, but I just want you to be aware.

One of the great reasons to use make or a build system in general

is because it makes it really easy to compile your code faster.

Notice how if I didn’t actually change, let’s see.

So I recompiled it because I just changed it again,

but now I haven’t changed it since I’m going to recompile or rerun.

Make just kind of like skips reassembling that file because it hasn’t changed.

it can make your compilations and assemblies much, much faster.

So anyway, functions. Functions in assembly are kind of simple and you’ll realize that

some of the stuff that we take for granted in higher level languages is being done for us

automatically by the compiler. But in assembly, we have labels. So for example, this start entry

some valid symbols like characters underscore numbers I don’t think you can start a label with

a number correct me if I’m wrong but I don’t think you can so we have like a label which is just like

this collection of characters and then we have a colon after it and so you can jump into a label

which I’ll talk about in a different video but you can jump into a label you can call a label as a

function and so a label isn’t actually a function by itself you have to treat it in a certain way

the abstract so notice how there’s no return statement at the bottom here let me write a

function real fast and maybe i will have it so that i have a function that just says hello for

me so i’ll make a label down here function that says hello and i’ll give it a label and i’ll say

maybe like say hello and i’ll do a little label there first thing that you should do when you are

trying to create a function is just put a return statement at the very end of it.

That way it will return to the caller because if you don’t then it’s just going to continue

to execute downward until it reaches no code and then the program will probably crash. In fact

maybe I should do that. I’m going to do say hello as a label with no return so it’s not really a

function now. It’s more of just like a label that you can jump to but there’s no code under it so

I’m not even sure this will assemble, but it’ll definitely crash if we can call into this.

So let me do, at the very start of our program, I’m going to type call say hello.

Or actually, you know what, maybe first I’ll jump to hello.

Jumping is going to be for a different video, but jumping just means go to that place.

It’s a go-to statement, essentially.

You’re not supposed to be able to return from a jump.

but it doesn’t really follow the same design pattern logic as a function.

So I’m going to immediately jump to the say hello logic and see what happens.

I think that it’ll crash.

Here we go.

SegFault, core dumped, oh no.

So, hey, it crashed.

So instead of jumping there, let’s do a call.

Now we’re treating it a little bit more like a function.

We still don’t have the return statement down here.

So it should still crash, I think.

Let’s try that again.

Yep, it crashed again.

Because you’re supposed to exit from the operator, or you’re supposed to exit from the program

properly to the operating system.

So now I’m going to do a return statement here.

There’s never an argument for the return statement.

You just simply return to the caller.

This uses the stack.

If you don’t know what the stack is, I’ll probably make another video about that in

the future.

But the stack, you know, it helps your program understand where it just called to and how

to get back from it.

to get back from it it also stores local variables and things but so if i have a call it should jump

down to the hello function and then return meaning it’ll just return to the caller immediately without

actually doing anything but the program should be able to continue without crashing notice how

there’s no crash here all it does is print out the welcome message and then no problem all right

printing stuff and I’m just going to cut it and stick it inside of the say hello

function that way when I call that function it should still print hello but

now notice how we have less code to deal with in this primary function you know

one of the first things that that programmers learn is that you know we’re

human beings we’re not computers it’s really hard for us to write complex

logic in a program without tools to help us and design patterns to help us to

help us stay on track to help us you know make sure that we’re not going to

we’re not going to be forgetting anything or screwing something up or you know to debug so

you know one awesome design pattern is to write functions because you you you realize in your

program you might be calling the same logic several times so you’re sort of like repeating a bunch of

code that already is bad it’s really hard to debug repeating code and it’s really hard to make updates

to it and it becomes unwieldy right so as soon as you realize you’re repeating the same logic

places you should think about taking it and putting that logic into a function

and then just simply calling that function many times it makes your coding

a lot easier and then once you put all the work into getting a function to

work you’re just you can just be done with it as soon as you’re sure that

this function actually works you can just put it to the side and just forget

about it you can stick it at the bottom of the source or just ignore it put it

into a different module whatever you want to do and then the other parts of

of the program that you’re still working on they become a lot more simple and so you know because

we’re human beings we need all the advantages we can get to write powerful code so i am now just

i’m not i don’t have to think anymore about all the system call things that’s happening

to print the hello message all i have to do is think about calling the say hello function

and of course this is simple but you can imagine using this for more complicated

concepts in the future so let’s see if this still works if i didn’t screw this up

It printed the same exact message.

And if I keep running it, you know, the make file doesn’t compile as much, but it still

runs the program.

If you don’t believe me that this is inside of a function now, let’s actually just call

that same function many times.

We’ll call say hello.

Let’s say we call it five times.

This should work.

I’m going to run the program again.

Notice how it printed that message five times.

Just to reemphasize my earlier point, wouldn’t it be a huge pain in the butt if you wrote

all the code for the system call and the message printing five duplicate times?

Wouldn’t that be hard to update? What if you had a hundred of those in there?

What if you had something that was really complicated and you called on it like

50 times,

wouldn’t that be so much better than maintaining 50 different versions of the

exact same idea of code and, and, you know,

making sure that if you needed to upgrade it or change it in some way,

you actually got it right for all 50 copies. So this is way better.

All right. So that’s the basic idea for a function.

for a function let’s see what else can i do um let’s let’s make a function that just prints

anything because that would be kind of a good little practice in the uh in the arguments that

we can use remember in c plus plus and other languages you have function signatures that

you can use so for example say hello we know for sure that say hello is not actually doing anything

it’s not receiving any arguments and it’s also not returning anything so if we know it’s not

returning anything. So if we know it’s not returning anything, we can say that it’s a

void function if we’re talking C++. We’ll do the name here. We’ll say say hello. And in the

argument list, we know that it doesn’t take any arguments. So it’s just say hello with nothing,

right? Okay. So let’s make another function that just prints something. And this function will

kind of be a little redundant because if you just sort of look at the system call here,

we have to load up the system call with the standard output and the system write code.

So that’s going to be repeated.

So we could move that into the print something function, but then, you know, giving an argument

of like, here’s the string I want to print.

And here’s the length of the string that I want to print that, that is something that

we can pass as arguments every time.

So we’ll be saving like a little bit of work, but it’s still, I think, I hope illustrates

the idea.

Maybe we will, oh, print something.

Okay.

So print something.

Maybe we’ll do the signature here.

Print something will not return any value.

So we’ll just give it a void return type.

And I’ll do a description up here.

Print a message given by a character pointer.

A pointer to a string.

character is also a pointer to a C string, not a regular string class, but a C string.

So I don’t know how to describe it. I think I’ll just say a pointer to a C string

and length and integer length maybe. So that means the print something function should take

two arguments. We want to be able to call that function and tell it, here’s a pointer to the

string I want you to print. And here’s how long the string is. So still talking about C++, I’m

character pointer p and maybe i’ll put like string just to remind myself when i look at this later

it’s a pointer to the string or like p char for the pointer to like the first character in the

string something like that and then length so the length is going to be a long because we’re using

64-bit integers in this video long and i’ll just say maybe size or length or something so now we

I want to use the same symbol that I’m describing in this little prototype here.

So I’m just going to copy paste it and use a colon.

And then because it’s a function, I immediately want to put a return statement at the very end.

Okay.

So then what I need to do is grab the incoming arguments.

Okay.

So, well, the first thing that every system call that prints a string should do,

at least if it’s going to print it to standard output,

to print it to standard output is it should start setting up the system call code registers or the

system call registers to say all right the system call wants rax to describe what the system call

is going to do we already have system write set up so that just means we’re telling syscall that

we want to print something where do we want to print it we want to print to the standard output

which if you look at earlier in the video that was just a file descriptor of one so that’s fine

up the system call and then the next two things can be kind of variable uh you know we can we

can grab that from incoming arguments so rsi wants a pointer to the string we’re not going to load

hello string but we’re going to load whatever character pointer we were given in the incoming

RDI is the first incoming integer argument.

We’re not going to talk about mixed arguments with floats.

If we just assume that we’re only going to use integer arguments or pointer arguments,

then the first one is going to be RDI.

So that means by the time print something gets called,

by the time we come into this code right here,

RDI should be loaded with the pointer to the character to the C string that we want to print.

Again, this follows something called the ABI, which you should absolutely respect,

which you should absolutely respect even if you’re the only one writing any of the code that you

interact with your code will be bad and considered not good if you don’t respect the abi on this type

of architecture so we definitely still need to load rsi with the string pointer but art whoops

but rdi is what’s going to have the string pointer so we actually already just ruined rdi when we

probably either load it up backwards or i think probably a better way to explain functions is

let’s just use another register so i’m going to use another register to sort of store our incoming

arguments i personally like to do this i admit that this will cost you cpu cycles to sort of

like move things around in registers but it’s still way faster than sticking something into

a global variable because then you’ll be hitting memory so first i’m going to say let’s move

to r12 and I want to store the incoming argument so I’m just going to write here save the

the p care you know c string character pointer or something like that so we’re going to save it

and then the next thing we need to do is save the size because as soon as we load up rsi we’re also

going to be destroying the second integer argument which should come to us in rsi

Okay, so I’m going to save that too, I guess, with R13.

So I’m going to move something into R13, RSI, and then save the size of the C string.

Okay, so we saved both of those.

Now, when we load RSI, we can just sort of say, RDI is saved.

And then when we load RSI…

Oh, that’ll be when we hit RDX.

Oh, that’ll be when we hit RDX. Okay, I got confused. So we stored R12 was the character

pointer. And then for the length of the string, we stored that as R13. Also for me personally,

I feel like it’s a pretty good idea to kind of make a comment at the very top, because this is

assembly. It’s really, really hard, right? Make a little comment at the top, just kind of reminding

yourselves what you use all of the registers for. I know sometimes you’ll use the same register for

sometimes you’ll use the same register for multiple purposes.

You could either write that down

or you could consider breaking up your function

into multiple functions.

That’s totally valid

and it probably will make your life a lot easier.

Anyway, so I’m gonna say register usage

and then I’m gonna say R12 pointer to string, C string.

And then I’m gonna say R13 is gonna be

size of the string. And that seems simple but remember assembly especially when you’re new

it’s really confusing and for me when I was first learning and even sometimes now I’ll be staring

at a big blob of assembly code and I’ll just be like what register was I using you know or I’ll

look at a register and I’ll be like what was that thing even for? So just make yourself a little

comment up here to help you understand and then you’ll thank yourself later when you get a little

a little bit too overloaded or maybe even if you come back to your code a month from

now probably having totally forgotten what you even wrote then you’ll just have a nice

little reminder here.

It’s good to document and this is one of the ways that I recommend.

Okay, so we’re saying that R12 and R13 are going to be used.

We’re loading them up here from the incoming arguments.

Now RDI and RSI are free to be destroyed if we want and of course we have to destroy them

because RDI and RSI were incoming arguments when this function first came in but now that

first came in but now that we’re going to be doing a system call we have to use

them for incoming arguments to the sys call so they’re just they’re just meant

to be constantly destroyed so we’re gonna do call code there and then the

standard output is gonna be the first argument and then the string that we did

which is an r12 is going to be the second argument and then rdx is going to

be the next argument which is r13 which came into us through the second argument

wait wait wait the string to write came into us through the first argument the

came into us through the second argument but if you just kind of look at what we’re doing to the

system call it’s actually the second and the third so I mean just forget about it okay so we set all

that up let me make sure I’m not forgetting something by scrolling up real fast yeah so now

we can do a system call one other thing that’s very very important about functions is you have

to respect the ABI and that doesn’t just include using the right registers for incoming arguments

out a call but you also have to keep in mind which registers are denoted as callee saved

if something is callee saved then that means you know if i’m inside of print something

i’m being called that means i’m the callee so that means if i’m going to use r12 and r13 which

are designated as callee saved maybe i’ll pull up that my favorite assembly book after this

but if i’m using registers which are designated as callee saved then i have to preserve those

then I have to preserve those registers, meaning those registers,

they should have their same values from when they first came in on the call

when I exit the function. So when I exit the function, those registers,

register values should appear to be untouched to the caller.

Remember these registers are not local variables.

They’re global to the entire system. There’s only one R12 on the whole CPU.

So every program that runs every function that gets called,

see the same exact R12 register. So if we’re not careful about preserving when we have to,

we could end up crashing other programs or our own program. So anyway, let’s do something that

I like to call the prologue and the epilogue. That’s another nod to my favorite assembly book,

which I’ll probably show at the end of this video. So prologue is just, hey, let’s preserve

the stuff that we need to preserve. We will preserve the R12 with a push and we will preserve

and we will preserve the R13 with another push.

We then have to restore them.

So right now when we do this push,

that just means that whatever value R12 and R13 had

is going to go to the stack.

So we’re going to hit memory.

That’s not great, but like we have to in this case.

We’re going to push it onto memory

in order to preserve the value.

And now we’re free to destroy the value if we want.

And then right before we return,

we’ll just pop those values.

So that means we’re going to go to memory.

We’re going to go to the stack.

to go to the stack we’re going to grab the values that we just pushed and put them back onto the

registers oops forgot to do 13 and 12 and I’ll call this the epilogue just meaning like we’re

done we’re cleaning up and of course look very carefully at the fact that the push and the pop

sequence are in reverse order notice how we push 12 first and we push our 13 second then at the end

Then at the end, we pop R13 first, so it’s backwards.

It’s like a little shell, you know, the R13s are on the inside

and the R12s are on the outside.

That logic would persist if we pushed,

or if we had to preserve more Kali saved registers,

if we were using more stuff.

The reason we do that is because the stack as a data structure

will return data to you backwards in the reverse order

that you returned it or that you sent it into the stack.

it into the stack so if i send a 12 and a 13 let’s just say the number 12 and the number 13

into the stack then if i start popping stuff out of the stack it’s first going to give me the most

recent item which is going to be the 13 so it’s going to give me backwards data and then it’ll

give me the art the 12 seconds so um the type of data structure a stack is is first in last out

last out no that’s a that’s a queue anyway so we’re preserving the registers we’re doing the

system call we’re probably okay to call this function now so let me see if i can do this

i’m going to comment out all of these things that the the say hello function does and i’m just going

to call on print something in order to call that function but i have to load up my arguments i have

pass arguments remember in the print something function it’s got a signature

it wants a character pointer and a size we can’t just call it without giving it

those things or it’s going to look at the registers anyway and just grab

whatever junk data happened to be in there so that would be bad so first we

have to load up the registers load up argument registers and call print

load up the argument registers and call print something.

So the first thing is going to be RDI, so we have to move something into RDI

and then the second register for the second integer argument is going to be RSI.

As far as I recall, if I’m wrong this is going to go horribly wrong.

I’ll double check the book after this.

And what do we want to do?

We want to basically, inside of say hello,

we could assume for now that say hello hardcodes the pointer and the length.

So we’ll just say it’s going to grab the string from global and it’s going to grab the string

length from the global variables.

So it’s going to load up those two arguments and then call on print something.

This still ends up being three lines.

That’s why I was saying before, we’re not going to save too much, but we did save, you

know, these two lines right here, you know, and the system call line.

So it’s like slightly faster to do.

You just load up two pointers and then you make a call.

in this video so I can’t really make the function better but in the future when

you learn how to loop and and learn about null terminated strings you could

basically just pass a pointer to just the string only and then call on a

function if the function was smart enough to scan through the string and

figure out how long it was based on where the null terminator was but that’s

gonna happen in another video anyway so if we call print something it should

Notice also that we’re having a function call another function, which is pretty cool.

So we have our entry point, it’s going to call on say hello, and then once we’re inside

of say hello, we’re just going to load up some arguments and then call on the print

something function.

The print something function then does most of the work for the printing, and I think

we’re ready to go.

Let’s see if this works.

All right, so we’re going to clear and then just run the program.

Oh, that was so fast.

That was so fast I don’t even feel like I’ve proved anything.

Let’s comment out the system call so that all we really do is just load up some registers

and then don’t do anything.

And then you should see here that the print something function no longer actually does

anything because it was too fast.

Now if I uncomment the system call, you know that the print something function is actually

doing something and it’s printing the message five times.

We can also make some more messages if we wanted to,

just as a way to make this video slightly more interesting.

I’ll say msg1 is going to be a string of bytes,

and I’m going to say this is message number one.

Boring, sorry.

And we’ll do a crlf there.

Actually you know what, let’s make a function that does a crlf.

Okay, let me just finish message one length,

and we’ll do it equals that special string that you can do in yasm am i doing this right yeah okay

so this is message number one so now we’ll call again with message we’ll call say hello just once

and then we’ll call on print something loading it up first move something with rdi and then move

message one is that what I had message underscore one and then RSI is going to

get message underscore one length so basically we’re just you know print the

first message it’s always a good idea to put comments on each line when you’re

learning so that you don’t forget what’s happening in addition to like a comment

for the whole block but I’m not going to do that here let’s just make sure that

make sure that this actually works so it should print two different messages now

one okay nice let’s enhance this a little bit more later i think i’m going to have us print like a i

don’t know a character or maybe we’ll do a return value from something so we can just show you how

to do the return values but i’m just going to enhance this a little bit more we’re going to say

let’s make another function we’ll call it crlf the crlf function i don’t want it to do all the

system call stuff because print something already does that for us i’m instead just going to make

message so now that means i’m going to go crlf and that’s just going to be a 13 and a 10. remember

you can define a c string with quotes but you can also separate quoted strings by commas and also

integers just to sort of tack it on so you know this variable right here it’s going to be a

sequence of characters representing the string that you see and then at the very end of the

string it’s going to have a crlf carriage return line feed so that the cursor goes to the next line

goes to the next line so I’m actually gonna take that off of message one

because it’s gonna be here just on CRLF and then I’ll say CRLF length is gonna

be two I could also do that special thing probably a little smarter CRLF

yeah I mean it’s it’s better to avoid hard coding things if you can avoid

hard coding the number two or any number just do it I guess I have to hard code

So, so CRLF and then length.

And so that means in my CRLF function, let’s see, let’s do CRLF, CRLF immediately return

because it’s going to be a function.

I’ll just say void CRLF with no arguments and prints a carriage return new line, also

known as CRLF.

and so that just kind of describes it and I don’t need to preserve RSI and RDI

because those are not callie saved registers so respecting the ABI kind of

helps you in this case I’m just gonna copy paste here and maybe I’ll copy

paste that comment real fast too so I don’t have to like type that whole thing

out and instead of doing hello string we’ll just say CRLF and then for here

And now when I call CRLF, it should just make the cursor go down a little bit.

So let’s test that out.

I took the CRLF off of message one.

So if we actually run this right now on modified, it should have the cursor.

Now, what did I just do wrong?

On number 28 and 29, instructions expected after label.

I guess I forgot to complete something.

Oh, I forgot to put, it’s a byte sequence right there.

there and I forgot to put that this is basically a defined sequence you know

that EQU okay my bad okay so now it prints notice how the message line it no

longer does a new line and no longer jumps to the next line CRLF so that

means when the program exits the terminal prompt is on the same line as

the program just printed that’s ugly and awful so let’s call

We could either say, let’s call CRLF after printing the first message,

or we could just assume that print something is like print a line.

I don’t know how you feel,

but I think if we always called CRLF after every time we printed a message,

I would probably be a little irritated.

So maybe let’s change this to print line and then make it call CRLF.

You can just keep adding this like 1013 at the end of every string, but I think I want

to try to make this as compact as possible.

So let’s add the CRLF for now and then we’ll change print something later.

So we print the message.

Now the prompt should be, you know, a line further down.

So great works.

I am now going to take the CRLF off and I’m going to put it inside of print something

so that right after we do the system call to print the string in question, we’ll print

we’ll print a new line this should now accomplish the same thing that we just saw

oh no what did i do i think i did uh i think i have a infinite loop of recursive calls in there

somewhere i had a stack overflow probably so let’s see what did i just do say hello is call

print something and then crlf is call print something oh whoops print something calls crlf

at the end so i should do one or the other and not have them call both so maybe just because crlf is

special maybe i’ll just use a direct system call inside of crlf i thought i was so clever

but i was wrong so we’re going to repeat a little code for the crlf and we’re going to load it up

with um crlf dang how embarrassing i like to say this is the most public of my many humiliations

of my many humiliations. But anyway, so now we don’t need to rely on print something. So this

won’t be an infinite loop and it should work if print something calls on crlf now. Do it again.

Okay, it works. So now let’s modify print something so that it is just print

a line. Print a line. And then that, in my eyes, you don’t have to do it this way. It sort of

to do it this way it sort of justifies printing a crlf at the end every single time so this is

just my personal thinking and then maybe i’ll add a comment after prints a crlf

so now when we call print line we no longer have to call crlf

and then when we print that message should be pretty good oh we got to update that to print line

Then for say hello, let’s just double check.

We can get rid of this system call code here.

Probably a good idea at this point.

And then we just say print hello string.

And then from the hello string, we can get rid of this CRLF at the end of it.

So I’m just going to get rid of that.

Actually, let’s do it first without getting rid of it.

Just so you see, oh, what did I do wrong?

Lion 61, forgot to update the symbol name.

Oh, there we go.

call print line because we don’t have print something anymore and try it again notice how

the first message hello my name is it has two line feeds after it because it is calling print line

which will do a crlf but then also in the string itself there’s a crlf so again the point is i’m

to my advantage.

Okay, so we got that working now.

I’m just going to print like five different kinds of messages.

How about three?

So we don’t have to sit here and watch me typing for too long.

So I’m going to say message two and then I’m going to do message three.

Message three.

This is message three unless I got that wrong.

One, two, three, one, two, three, one, two, three.

Now we can just call a print string on three different messages.

And I’ll just change this to say, you know, print the second message, print the third

message.

And then I’m going to change that to message two and then message three.

All right.

So then I’m going to do that again.

And then all three messages get printed.

Nice.

So now one more thing.

I just want to show you how to return an integer to the caller in a basic YASM x86 assembly function.

Again, this will not cover floats.

This does not show you how to return floats.

With floats, you have to use a different register called xmm0.

That’s going to be a different video.

But for now, I’m going to say all integer or pointer return values, like longs is going to be what we’re using,

that is the register that is designated for return values.

So what about this?

Instead of just returning the exit success code

that I’ve defined up above,

we’ll return whatever some function call gives us.

Maybe I’ll make another function down here

and then I’ll say a function

that just returns a simple long value.

And we’ll call this function gimme long.

We’ll call this function gimme long.

It’ll take no arguments because we’re just keeping this simple for now.

And instead of having a void return type, it’ll have a long return type because we expect

RAX to be loaded up.

So then I’m going to say gimme long and immediately do a return because it is a function.

And then I’m just going to load up a value from somewhere.

Obviously, it’s better if you’re doing something complicated to stick with registers as much

or defines and hit memory only if you need to.

And try not to hard code immediate into your code

if you can possibly avoid it.

It’s probably a lot better to define a value up at the top

in the data area than to just hard code it here.

But I’m gonna just hard code something here.

No, I always second guess myself.

I’m gonna say exit gimme.

I’m gonna define something up here.

So it’s easy to find what value I’m gonna return

for the gimme.

I’m just going to say 88, 89, 90, I don’t even know.

About 33, I don’t even know.

So we’re defining exitGimme as a symbol

to just be a replacement of just the number 33.

So down here, I’m going to say,

let’s have gimme long simply return exitGimme into RAX.

Nice, okay.

And so that means it’s the official return value

once you call gimme long.

call gimme long so that means up here get our whoops get out it’s coming from inside the house

get our return value from gimme long and again imagine gimme long might be a big complicated

function that decides what a return value is going to be or does something so i’ll start with saying

call gimme long because gimme long does not take any arguments i don’t have to load up any registers

load up any registers nor do i have to worry about preserving them or setting them up or doing

anything i just call but then let’s see inside of this function we’ll use rax in order to you know

load up the system call to let it know what function or sorry what function we want from

the system call so we got to give rax system exit so that means down here we can’t actually use rax

those other registers again I’m going to use I’m going to use the r12 register

I’m going to do like a little comment here that says register usage and I’ll say r12

maybe I’ll do a tab r12 is going to be old return value

or the syscall to exit you know whatever and that’s all we’re going to do so in the prologue

I’m going to push R12.

You should probably even preserve registers in the start function

because something might, or in your entry point,

because something that called you might be counting on those registers.

This is going to be probably especially true if you’re using GCC

to have a main entry point within a hybrid program.

So I’m just going to go prolog, push R12,

and then pop R12 at the very end.

Pop R12.

That’s not going to work because by the time we get there,

because by the time we get there,

it’s gonna exit the program.

I’ll do this here.

I’ll just try to be a good citizen.

I’m not actually sure if we need this

for a pure assembly function,

but it’s just a really good habit to get into.

And what is it gonna cost you?

Just a touch memory,

just one time right before the program exits.

It’s not gonna be a giant for loop or anything.

Okay, so epilog,

probably I might be showing you bad practice

by preserving things in the underscore start function.

But again, you will definitely wanna do this

Again, you will definitely want to do this for the main when you return from main.

So we do prolog R12, epilog R12.

I made a comment there.

And then we’re going to store the return value in R12.

So that means here we’re going to move something into R12.

It’s getting precarious because we restored it right before the system call,

but I think it’ll be okay.

system call but i think it’ll be okay we’re going to grab rax because rax is supposed to be the

return value register so when we called gimme long it loaded up rax with our return value

we then send rax into r12 so we can use r12 uh even though our rax has been you know destroyed

we’ll still have the return value that we wanted to use so i’m just going to load r12 up into the

first argument of the sys exit call let’s see if i if i got this to work or if i totally ruin this

work or if i totally ruin this okay all right so let’s see here what was

why is it not erroring gimme 33 exit gimme should i did i load the wrong value exit gimme what is

it doing exit gimme it’s moving rex into exit gimme so you call gimme long and then you move

r a x into r 12 and r 12 i wonder if that destroyed it

hmm let me get rid of this push pop pair because it’s supposed to be giving me

an ever message that the function or that the program did not exit maybe this is proof that

you don’t need to preserve inside of the underscore start function let’s see here

yeah okay i guess that proves it hey don’t take my word for it i’m wrong all the time

For yourself, be a scientist, be a computer scientist.

Try it out.

Try to do something different.

Okay, so I guess this is proof we don’t really need a prolog and epilog in just a pure assembly,

at least the entry point for start.

But if you were calling any other functions, then they definitely need to preserve.

And again, if you’re using GCC, so you can have a main for your entry point, then you

still have to preserve.

you know print the message and then print our other three messages and then the return code

is going to be 33 that was the gimme code that we did so now we know how to return a value from a

function and um let me set this back to just zero so the make system thinks that we succeeded

run it again succeeded all right i guess this concludes the video i hope you had a little bit

and I hope you learn a little bit of stuff and I’ll see you in the next video.

Hey everybody, thanks for watching this video again from the bottom of my heart.

I really appreciate it.

I do hope you did learn something and have some fun.

If you could do me a please, a small little favor, could you please subscribe and follow

this channel or these videos or whatever it is you do on the current social media website

that you’re looking at right now.

world to me and it’ll help make more videos and grow this community so we’ll

be able to do more videos longer videos better videos or just I’ll be able to

keep making videos in general so please do do me a kindness and and subscribe

you know sometimes I’m sleeping in the middle of the night and I just wake up

because I know somebody subscribed or followed it just wakes me up and I get

filled with joy that’s exactly what happens every single time so you could

do it as a nice favor to me or you could you control me if you want to just wake

just subscribe and then I’ll just wake up. I promise that’s what will happen.

Also, if you look at the middle of the screen right now, you should see a QR code, which you

can scan in order to go to the website, which I think is also named somewhere at the bottom of

this video. And it’ll take you to my main website where you can just kind of like see

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

clarifications or errata or just future videos that you want to see please leave a comment or

if you just want to say hey what’s up what’s going on you know just send me a comment whatever

i also wake up for those in the middle of the night i get i wake up in a cold sweat and i’m like

it would really it really mean the world to me i would really appreciate it so

again thank you so much for watching this video and um enjoy the cool music as as i fade into the

which is coming for us all.

Thank you.

Comments

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

Leave a Reply