 I should have got a NYCHA shirt, this is my gardening shirt. Anyway, so I've been having a lot of fun over the past two years working on different, well, learning about assembly, language, and implementing some stuff. And I did a lot of work over the past year and a half, two years. And let me just show my screen. I worked on this, I call it skid solo, which is scientific computing, homemade implementation zone. Basically it was a bunch of libraries and examples that went from the bare bones, like the basic stuff like file.io and printing and vector algebra, all the way up to vector graphics and advanced engineering stuff. But the problem was, what you don't realize is six months of learning something and then a year and a half of implementing what you know, you realize that at six months you thought you knew a lot more than you actually did. I'm Dunning Kruger and I wish now that I'd done things differently. And so I thought, you know what, why don't I go back and kind of redo things a bit differently, a bit better in some cases than what I had before, also a bit worse in some cases. And just to make things a little bit different, fix things along the way and then take the YouTube channel along with me as I go. And that's what this series is. And this is episode one. We're gonna talk about a minimal executable, but this will be at least 30 or 40 episodes long before we get to like the end of kind of things that I'm willing to cover. So yeah, that'll be pretty cool. And basically what we're gonna be doing in a nutshell is everything entirely from scratch. So like it says, no dependencies or even standard libraries. We're not gonna use printing, print F. We're not gonna use any of that stuff from standard Libs. Every instruction you can see here from scratch, every instruction that we're writing that the program is executing, we are writing with some very few exceptions. Those being syscalls. And if you don't know what a syscall is, don't worry neither do I, but we're gonna be using a couple of syscalls to do certain things like reading files, writing files, changing file permissions, creating files. And also I think we have one to leave the exsys exit is to leave the executable. So I think we're using just five syscalls to do everything we have to do. Just the bare bone stuff. Every other instruction, every other machine instruction, we are writing ourselves, well, we're gonna use ourselves from scratch and construct more advanced algorithms from those instructions, right? And also not only that, but we're also gonna be using a very minimal executable format. On Linux, by the way, this is all for Linux and VSD. Everything's in ELF. All these executables are ELF formats, right? So we're gonna kind of be using the bare bones ELF file, not the one that's full of garbage that the C compilers and the Rust compilers and stuff kind of create for you. And they create those things because they want your program to be able to be debugged, they want to be able to be used with other utilities and stuff like that, which is fine, but for me and someone who has a very small brain like me, we need simplicity, we don't need all this extra layers of complexity. So with that, I'll get into one disclaimer which I think is kind of important. It's that I have no idea what I'm talking about. Everything I say is likely incorrect. When you go to a college class, the professor and the TAs, they know everything and the textbook knows everything and they teach you everything and they throw information at you, which is great. You get all the information you could ever want. That's awesome if you can absorb it. I didn't go to school for this. I went to school for a different field entirely, but I know and you probably would agree with me if you've been in this situation that you don't remember that stuff more than a year, two years. If you get a job and you don't use it, you lose it. So a lot of things that I learned in college I don't use. I mean, obviously it wasn't in short-term memory and I don't know it anymore. So I mean, I'm probably familiar with it and I could probably figure it out, work through it, but it's not in my brain. And that's kind of the advantage of doing things kind of from what I'm doing here, which is going in a very practical way and just diving head first in something and learning it yourself, piecing together what works, what doesn't work, seeing what gives you an error, what doesn't give you an error, seeing what kind of exceptions you get, seeing, looking through the manual, looking through forum posts, looking at all the executables, looking at Stack Overflow. There's a couple of guys on there that are awesome. Two or three guys are fantastic. You can read their posts and learn so much from those guys. And just that process, it's very different. It's not like you have a bunch of information. It's like you have a line of information with a very clear trajectory. I needed this one to do this one and this one to do this one and this one to do this one. Everything had a clear reason and it's like that why and the how that makes you remember it forever. I will never forget what I've learned over the past two years. I don't think because everything has a purpose and a reason and I had to go through and figure that out each one on its own. You don't get that kind of a network in your brain when you just get information and thrown at you on a whiteboard in your college classroom or whatever it is. So yeah, for that reason, like it says, I have a letter I'm talking about but that's a blessing and a curse. Not having that official background and a collegiate experience means that I had to figure this out on my own which again can be bad but it also has its advantages. I can kind of bring people, I give you a second opinion basically but what I understand versus what the professor would say is the truth. Okay, with that out of the way, I don't want to waste any more time. It's six minutes and G's already while I was long. I wanted to make a minimal executable and you see here I got a boomer and I got a zoomer and these people's ideas of minimal executable are just wrong. The zoomer is even more wrong but the boomer is wrong too. A boomer would say, oh, a minimal executable would have to return zero or return a number or 42, right? Very cringe. That's fine but it's not minimal. Maybe it's minimal in C or something. It's not minimal in assembly. Maybe it's minimal in MATLAB. It's not minimal in assembly. In my opinion, in my opinion. A zoomer would say, oh yeah, pretty hello world. Yeah, console log hello? No, this guy's dumb. Millennials, as usual, we have to clean up the place. So they're right. Infinite loop, true. And if you can figure out what instruction right here right now without fast forwarding or cheating, what instruction are we gonna use for infinite loop, a minimal infinite loop? You could be my friend. So that's awesome. So we're gonna be doing this. Now the first thing I wanna talk about because it's kind of important is what's the tool chain? How do smart people, not like me, but how do smart people create executables? Well, what they do is they take their C code, their assembly code, their C++ code. They take, if they're maybe having this kind of a mental problem, their Rust code, right? The Go code. They're running through a compiler and they get these object files. And then maybe take some pre-compilations of libraries, maybe like the print def, maybe like the math libraries and they'll link them together with the linker and they'll get an executable binary, which is a kind of Elf file. We'll talk about Elf files in a minute. And it's great. This process works and it's for geniuses. It's for PhDs. It's for, you know, MENSA scholars, IQ 197 minimum to do this. Now, simple things like me, we can't comprehend this. Clippy is right. He says the smaller the brain, the smaller the tool chain. Very true Clippy. Why is the words of wisdom from Clippy as usual? We just gonna take the assembly code, run it through the assembler and get a binary out of it. And then we're gonna make that binary executable and run it. There's no fancy linking, nothing like that. We're not gonna have any standard libraries that the NSA is gonna use to watch us. No, no linker, no libraries, no dependencies, no other languages. One tool chain iteration, basically, the assembler. And by the way, you don't even need that. If you really want it to be base, you would just write things in zeros and ones. But me, I don't speak zero and one, I speak English, so we're gonna use the assembler to translate from English mnemonics to zeros and ones. Now, I can already sense like the 20% of the audience who are really like boomers, either IRL or in disguise saying, oh, you must use the linker. You must use the linker, all this stuff. You need the linker to make your binary executable. Without it, the OS won't know how to load your binary into memory and run it. Yeah, yeah, yeah, yeah, yeah, yeah. True, the brainlets are right, but we don't need to use the linker to do this. This is what the linker does. We don't need it. If we write just everything ourselves, including what the OS needs to know about our zeros and ones in order to run it, we don't have to use the linker, which is what I'm gonna talk about today. And so to the boomers, I was responding to the wise words of Obama, he always said, no you. So with that out of the way, I wanna talk about the ELF header, what ELF files are and stuff like that, just briefly in phone Wikipedia, and then we'll fill out a little table here where we're gonna juxtapose compiled C, or a minimal executable, like the infinite while loop, in C, in a linked assembly, which is like boomer assembly, and then we have our direct assembly binary as well. We'll juxtapose how big those files are, how complex the headers are, and all that. So I think it's pretty interesting. We'll take a look. So the first thing, I wanna show you, was the ELF header. So on Linux and on BSD, this ELF header is basically what tells the, let me open up this picture, it's what tells the zeros and ones in your file, it's what tells the OS what those numbers mean. So the first couple of zeros and ones, 64 bytes on our 64-bit OS, 64 bytes are the ELF header, and that just says, hey, the file that you're looking at is an ELF file, which means it's either executable file or a library file or whatever, and also here's how you should open it, right? And the program header basically says, okay, well, these sections of memory in the binary are this big in the binary, but they're actually meant to be this big when you put it into memory, and here's what the permissions are, here's how to execute that, all this stuff, and those two things are all you need. You only need one ELF header because we have one file, and you only need one program header because you're only loading ideally one chunk of code into memory. Of course, the boomers, they get their Grammy hands on stuff and they make things overly complex. They add layers and layers of paint. It's like, you have this piece of wood, I got a prop, a piece of wood, and you apply layers of stain and paint, 10, 20, 30 of them until you no longer can see the grain of the wood, and it's like, it's nuts. If you understand why they do that, they do it because they want their code to be, hold on, they want their code to be, when they execute it, they want to be able to pull it into other utilities to put it in a debugger and stuff, but the issue is that it's just overly complex for someone like me, and you'll see how bloated the file is, which again, it's not a huge problem. We have 10 terabyte hard drives out there you can get, but it's still, it's not ideal. Everything else you see here, dot text, these are just sections. So basically, the boomers, they put their instructions in the text section of a somebody's file, they put their read only data in, I think that's what it stands for, the RO data section, and then they have their regular, volatile memory, or whatever, the memory that they're gonna change things in data, and that's how they do it, and they have a section table, which kind of defines where the sections are, what they're called, and that's like for debugging and stuff. Again, it's not, I mean, it's useful, but not to us, okay? And that's what the header is, and just to go into some details here, like the first four bytes, so address zero in the binary, that the zeros and ones, the first four bytes are basically this number followed by ELF, just to tell the operating system, hey, this file, it's an ELF file, and then you have a bunch of stuff, you put like two for 64 bit, you'll put all the stuff for ending this, you'll define your ABI, again, doesn't seem to matter, actually. You can put system five, you can put for BSD, you can put Linux, I think it all seems to work, I don't know if that's supposed to be a feature or a bug, but anyway, yeah, we're gonna fill all this garbage, I'll get to that in a minute, that's the section header, and then you have the program header, which is again, how to load this into memory, what it is, and all that, so again, you have 64 bytes of section, or sorry, ELF header, and then you need at least 56 bytes of program header, so you have one program header, and then your program can start, so that's 120 bytes of just boilerplate at the top of your program that you need, minimum, and then you can start your program, okay? That's kind of what my Champaign-Z brain understands on this, you need 64 bytes of ELF header followed by 56 bytes of program header, and then your program can start, that's the minimal ELF file. So with that out of the way, I wanted to populate this table, showing you a couple of these different examples, in C, assembly, and then direct assembly, and yeah, this is just gonna be a wild-lip, so let me pull up my computer, so this is a, I made a quick virtual machine for FreeBSD, I wrote the whole code on FreeBSD, but I just wanted to show you what a clean install, you know, how this works, so we only have a couple of things, hold on. We have, we have NASM, that's gonna be our assembler, we're gonna use, I think it's called Intel syntax, and then we also have a C compiler, which version I think, because we're using Clang, doesn't matter, it's just to drop the post stuff, long-term we're not gonna use C compiler, we're only gonna use NASM for everything, but just for our first episode here, we're gonna talk about the C compiler, just to juxtapose the two. So, this is my program, my repository, my Soil Hub repository, and I'll put it up for you guys in the description, you guys can take a look, but oh, we need a license here, let me put a license. All right, that should be good. So, if I go into my examples folder, I have an example one, minimal executable, and in here, I have a couple examples, I have the C version, I have the first boomer version of assembly, and then I have our minimal executable. So, let's go to the C one first. In here, I have two files, I have a main function, obviously you need, this is my code.c file, I have, this is just the int main, while one, this loops forever, it has return zero, but it never will, because it will loop forever, obviously, and then we have our shell script, I don't use make files, make files are from the devil, I call them snake files, so yeah, we use just this, so first thing we're gonna do is cc code.c binary, we're just gonna make the binary with a C compiler, and then run it, so that's simple enough, if we run this, you can see it hangs, this binary is running, it loops forever, while one, success, minimal executable done, however, it's not so minimal, check out this, if you look at the file size, I'll write this down, it's 14,672 bytes, right? Word count binary, yeah, 14672 bytes, it's immense, I said before, we only need 120 bytes of boilerplate, and then the loop, by the way, that's a two byte instruction, so you only need 122 bytes, minimum, yet the C compiler made 14,000 byte executable, and yeah, you can optimize your size, but don't worry, it's not gonna get anywhere close, it's really gonna help at all, so that's one thing, and now there's actually a function called readElf, you basically can check what the elf file has to say, and so if you look at this, you'll see at the top, you have the elf header, it's breaking it down for us, what's inside there, and two things I wanna point out is the number of program headers, again, you only need to have one, it has 11, I'll write that down, and then it has 37 section headers, you need zero, why does it have so much? It has so much, it's all full of garbage, and here, let me show you, all this stuff, it's all garbage, this is all parts of the boilerplate for our wild loop, why? This is the C runtime at its worst, so yeah, it's all garbage, and that's enough of that, so if we go back to our second example, this is the boomer assembly example, so in here I have two files, I have code.asm and I have room.sh, so this is what boomers do for assembly, this is like the bare minimum assembly file for a boomer, you have a global start, that basically means I have a label in my, there's an address that I'm calling underscore start, that address I wanna expose that to the rest of my program when it's linked later on, and yeah, that's what that line is global start, it's a globally identifiable label, then as I said before, section text, that's where the boomers put their instructions, that's what we're gonna do, then they have their entry point label, and then they have, this is the minimum thing to do, it would just be jump start, that's the minimum wild loop, basically you jump back to this label over and over and over and over again, here's the entry point start, first instruction is jump to start, so you jump back, this is as easy as it gets, actually let me show you, I have it open actually, this is the jump instruction, this is the opcode, so EB means jump short, so basically that opcode, if you look at the zeros and ones, the hex decimal EB, that means jump to within a very short range of where I currently am, and then the next thing after that is kind of how far, and because this is a two byte instruction, EB distance, each one is one byte, that would mean that you're just gonna constantly be jumping back two bytes, so and if you know, for eight bits, negative two is just FE, right, yeah so your command is gonna be, your code is gonna be EBFE, and that's gonna be your entire code, that's your entire binary that's actually running, is just one opcode of two bytes, and the value of that instruction is EBFE, so with that out of the way, let me get back to this, make sure you can see what you can, that's what the assembly language looks like for boomers, and then you have the shell strip that compiles it and runs it, so we're using NASM, making it an ELF 64 type format, and we're linking it with a linker, again, why we're doing this, I don't know, because boomer said so, and then we're running it, and if you want to, you can strip some symbols from this to make it a little bit smaller, but really it doesn't help that much at all, like before, so we'll execute this, and I'll show you how it works, so you see, again, it loops, it's successful, it's hanging, there's no error coming up, it is looping forever, and if you look at the file size of this binary, it's 880, so it's way less, so here 880, file size is way, way, way smaller than what it was before, it was 14,000, now it's 880, if you look at the read ELF, you'll see this time, there's four program headers, and six section headers, so definitely an improvement, it was a lot more before, but it's not anywhere near where it needs to be, this number should be zero, and this number should be one, and if you go through, you can see that all this crap is still here, not as much, but there's still a bunch of crap in this file, and by the way, if you were to strip it with that strip command, some of this would go away, but not all of it, so anyway, that's that, and actually at this point, I'm gonna actually dump the binary for you, so if you hex-dump the binary, I think you hear this, I think, oh no, we can't, hold on, that's, so here you can see the actual, this is the actual binary in memory, that we've just created with that NASM and the linker, and you can see at the top, here's that magic number, and by the way, the ending in this is such that things are switched around sometimes, so don't worry about that, but here is that ELF header, the first 64 bytes, so from zero to zero all the way to the 40, so these four lines, that's the ELF header, and then everything else is program headers, section headers, an actual binary, and here, FEB, this, remember I said it was EBFE, that was the jump instruction, here it is, EBFE, so that's the only instruction in this program, everything else is just garbage, everything else is useless garbage, this whole thing is waste of space, except for that one instruction, of course you do need some of it to run the file, to tell the OS how to load it into memory, but you don't need all of it, you only need that single two byte instruction to actually run it, so that out of the way, I'm gonna go to our last example here, the sort of bare bones ELF file here, let's open it up, so I've got two files, again, code.asm is the assembly file, and then we have run the sh, let me show you the sh one first, see how simple this actually is, in this case we're not using the linker, well what we're gonna be using is just NASM, so we're gonna use NASM and make a binary with NASM, so dash f bin that makes a format binary, called binary from code.asm, and so that string of commands means, and all we have to do is because of Linux and BSD being kind of cringes, you have to make it executable before you can run it, so chmod plus x means make this binary executable, so that's what that does, then it runs it, so really we have one tool chain step and then we have one Linux BSD compatibility step, ultimately. So I go back to the assembly file, I can go through this, let me just show you what's going on, I have a ELF header, so you can see here, a lot of that crap about what the program is, here look at this entry point, I call it start, I'll show you that in a second, everything here, these are all like NASM, syntactical things, so DB means define bytes, so here we're defining four bytes, the first one is 7F, the next one is E, then L and F, then this one is two, D times means do this, here in this case, seven times, DW means define two bytes, DD means four bytes, DQ means eight bytes, right, all that, that's all this here, this is the ELF header, that's 64 bytes total, this is the program header, that's only one of them, 56 bytes, and you can see we're doing some algebra here to compute things that are of interest, and I have everything explained on the side about what each line is, you can peruse this at your leisure, and then here's the actual code, and here's how I will format every single assembly file from here on out, well every single example, we're gonna write assembly files that are functions in later videos, but this is like the actual executable itself that calls the function, that executable needs to have this format in my monkey brain, first thing I put in here is includes, here's where we include literally what the macro for NASM is, percent include, and you can include a file, so you include funk1.asm, and it will include that function, it'll literally paste the function here, it will go to that file, copy it, and paste it here, that's what it's gonna do, and so we're gonna put all our includes in this chunk, so all the things that we could possibly need to call are gonna come before, and it doesn't have to be before, it could be after, but before we're actually gonna start the program, so start is our start address, and end is the bottom of the, the end of the instructions I'll say, we will eventually put stuff below end, like we'll put our dynamic memory, we'll put our heap and stuff at the bottom, and I'll tell you about that in a later video, but for the time being, this is our entire program, we have one start address like before, like the boomers had, and our only instruction is jump to start, and if I go back to the top, remember I have a start and end that surrounds the instructions, so I'll go back to the top and I'll explain some of the other stuff that we had, so load address, this number can be anything, I think it has to be more than zero, but it seemed to work for me if you put any number in, this basically means when the OS loads your code into memory, your binary into memory, what address will it start at? So here I have org, maybe that means origin or something, it just means that everything after this will be with respect to address 20,000 hex, this number here, so put whatever you want, you can put in like 10 or whatever, I think you should make it a multiple of like 1,000 hex or something, but whatever number you wanna put in, you put in, it's fine, then I'm defining another variable, so percent of mine defines, it's a macro that defines a local variable, it's not a register, it's not a value, it's just for the assembler, it has no, it's not gonna be in your code, it's not gonna, it's not gonna be, well I guess it could be, but it's not gonna end up, this number, it's not gonna be zero x, zero five three one two a e, it's just for the assembler as it goes through to use this and put it in location, so in this case it uses load address as the origin, this bits instruction, basically the problem, I'm gonna go here, the problem with NASM is that when you do a binary, it assumes 16 bits for whatever reason I think, and so if you say bits 64, that means everything after this assume it's 64 bit, so that's what that means, and then if I go through here, you can see one of the entries in the ELF header was the entry point for our program, and there I just put start, so this basically will plug in the address of start which will be like 20,120 I guess, and it will put that number smack dab here, right, simple as everything else is hard coded, that's not gonna change, right, hard coded stuff, and by the way I said this could change, right, it can change if we were to add, what if you were to add 100 bytes of functions here, then it would no longer be, this would no longer be address 120, it would be address 220, and actually it would be address 20,000, 220 because it's all with respect to that load address, and so yeah, here's the address of that start location and you can see again here it's that location, so this is just the offset to this point in memory, actually no, sorry, this address will always point to the includes, so both are headers combined will be 0x78, I'm pretty sure that means 120, let me check actually before I, it's not like an idiot, 120 in hex, 78, yep, so yeah, that's, oh geez, what do I do, what did I do, oh no, yeah, so this basically means at address 20,000, 120 will be our virtual memory start location, again this is not important, this is just gonna be stagnant, then these two things are actually important, code size means this is how big our program, this program header is referring to a chunk of code, code size, remember that was the distance from start, actually it was the distance from like here to end and so yeah, that will refer to that quantity, and then this one refers to how big that should actually be when we put it in memory and in this case it's the same size, but if we were to add like a heap and we were to add like some other stuff, we're gonna have to add to this, we're gonna have to say like keep size plus buffer size, other stuff, right, so we may have to add to this one later on to support the dynamically allocated memory or memory that we don't wanna have in the binary, we don't wanna have it on our hard disk, but we actually do want to have more memory to use for variables as we go, hope that makes sense, that probably doesn't, if it doesn't, let me know, and that's that, so we can take this and we can run this, I don't know what did I do, if I run this, again it hangs indefinitely, but the cool thing about this is that the file size is, you can see here, the expected value of 122, right, that's 64 bytes header of elf header, if you take some bytes of program header, two bytes of exit readable, of actual instructions, and so I can actually dump it for you first, hex dump the binary, don't even need less anymore because it's so short, look at this, so the first, everything from zero to zero to the end of three zero, this line, those 64 bytes are the elf header, then from 40 all the way to here, I guess that would be 78, that is your program header, and then the prophetic feed, this is our eternal jump instruction, and you know, if you wanted to be a troll, if you wanted to open up someone's binary and change one of the instructions to feed, you would cause their program to break, if it ever got to that line, it would just loop forever indefinitely, so if you want to be a troll, you can do that, but yeah, this is it, this is basically the minimal executable that we're talking about, and again, we're gonna add more to this, we're gonna add more instructions, more complicated programs, obviously, just a while loop, but the overall framework is there to handle all this, if I go back to the code, oh, what did I do? Oh, that's just the binary, oh my God. These things will update, right? If I add more code, this will update, if I want to add a heap, I have to define some stuff, but I can add a heap, if I want to, I'll get into that in all in later videos, but that will all be easy to handle. Now, if I go to read elf, you'll see that in this case, we have only one program header, and we have zero section headers. Again, that's the minimum that you need for your program to run. Alrighty, so with that out of the way, let me go back to our little table here, and let me draw these numbers in. So, the binary for the C1 was 14672, the binary for the Boomer assembly version was 880, and you could get these numbers a little bit smaller by using the optimization flags and by stripping them, but you won't get anywhere close to what this one was, which was 122. That's the minimum number of bytes you need. It is literally a minimal executable fact. Actually, it's not a fact, because I'll put a link in the description, there's a guy, he has like, it's called like a whirlwind tutorial and something in like elf binaries or whatever. It's, he actually kind of folds the headers together and he kind of embeds the program inside itself. That's cheating, but it is less file size, but again, it's not extensible. So, you can see here, we are 120 times better than C was, just for a simple while loop. And of course, as you add more code, this boilerplate becomes less and less important. But, you know, this is still there. You still have 14 kilobytes of garbage in your code. And you know, it's not just garbage. It's not that it's garbage, it's that you don't understand it. You have to have like 30 years industry experience, you know, in this particular stuff to know what all that stuff means. I will never get there. I will die long before I'm at the, you know, place where I can understand what the, what everything in the C, you know, in the elf header for the C compiled binary actually is used for. So, never gonna happen. Section headers, the first one was 37. The next one was six. But of course, you don't need any. You don't need any of them. And lastly, we had program headers. There were 11 program headers in the C version. I think I wrote down there were four in the Boomer version and then there were just the minimum of one in our version. So, you can see at the end of the day, we win. Hold on, where is my box? We win. Everyone else is losers. We are winners. It's not every day that the monkey brain wins, but today we win. So, yeah, that's pretty much what I wanted to share. We have a minimum executable that we can add stuff to. In the future videos, we're gonna talk about registers and the stack, calling convention, system five, ABI. Well, I like about that. Well, I don't like about that after having used it for, you know, many, many, many, many programs. Things that I think I could probably do differently, not better, but just ways that I wanna think about things differently. We'll talk about some sys calls. We'll talk about file IO. We'll talk about printing stuff to the screen. Again, all of this is gonna be done manually by us. We're not gonna use any libraries. Nothing like that. With that done, I'm losing my voice right now. Thanks for watching. This was a long video just for this little topic. I'm surprised how long it was, but we covered a lot. And if you stuck in to the end of this, I'm really thankful. Again, these videos aren't monetized. I never will monetize that. It's really cringe. I don't care about likes or subs or views. What I do care about is like, people will leave nice comments. It's like, I don't have very many people that message me on my phone. So when I get a vibration, I'm like, oh, wow, I'm popular. And when I see someone that says, oh, wow, thanks for the video. Much love from Argentina. You know, it makes me happy. So if you want to make me happy, leave a comment. Otherwise, I couldn't tell us what you do. Thanks for watching.