x86 Assembly Language Programming Masters Course | Daniel McCarthy | Skillshare

x86 Assembly Language Programming Masters Course

Daniel McCarthy, There is always more to learn

x86 Assembly Language Programming Masters Course

Daniel McCarthy, There is always more to learn

Play Speed
  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x
26 Lessons (3h 26m)
    • 1. Introduction

      0:53
    • 2. What Is Assembly Language

      1:47
    • 3. Installing The Emulator

      2:00
    • 4. Creating A Hello World Program

      17:45
    • 5. Understanding The Processor Transistors And Logic Gates

      12:56
    • 6. Registers In The 8086

      9:52
    • 7. Memory Segmentation

      8:52
    • 8. The Stack, Subroutines And Endiness Explained

      8:37
    • 9. Moving Data To And From Memory

      8:58
    • 10. Interrupts And How They Work

      13:59
    • 11. Talking With Hardware With In And Out Instructions

      3:10
    • 12. Mathematics Adding, Substraction, Division And Multiplication

      15:13
    • 13. Condition Instructions

      8:22
    • 14. Reading bytes with the lodsb instruction

      2:45
    • 15. Storing bytes with the stosb instruction

      2:21
    • 16. Revising Our Hello World Program

      7:09
    • 17. Helpful Resources For The 8086 Processor

      2:09
    • 18. Installing x86 Assembler Dependencies Revision

      5:42
    • 19. X86 Hello World

      6:10
    • 20. Using Assembly With C

      21:46
    • 21. Local Variables In Assembly

      14:05
    • 22. Returning Structures In Assembly

      13:55
    • 23. Pointers In Assembly

      3:51
    • 24. Passing Structures To Assembly

      7:30
    • 25. Receive Input From The Keyboard

      5:47
    • 26. Conclusion

      0:21
  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels
  • Beg/Int level
  • Int/Adv level

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.

149

Students

--

Projects

About This Class

This course is intended to teach you x86 assembly programming. This course teaches you how processors work and how machine code is possible. We start the course using an emulator for the legacy Intel 8086 processor.

Since we start the course with an emulator it allows me to pause the machine at any moment in time and show you exactly what is going on.

After you learn all about the legacy 8086 processor and how to program assembly for it we then move to the modern processors of today and start writing assembly for those. You are taught how to write 32 bit programs for Windows machine's and most importantly how to communicate with C programs using assembly language.

This course recommends that you have some prior experience in the C programming language or at the very least some programming experience in another language. The reason for this is because part two of the course when I teach modern assembly I reference the C programming language quite a lot since we write assembly that can talk with C.

Meet Your Teacher

Teacher Profile Image

Daniel McCarthy

There is always more to learn

Teacher

Class Ratings

Expectations Met?
  • Exceeded!
    0%
  • Yes
    0%
  • Somewhat
    0%
  • Not really
    0%
Reviews Archive

In October 2018, we updated our review system to improve the way we collect feedback. Below are the reviews written before that update.

Your creative journey starts here.

  • Unlimited access to every class
  • Supportive online creative community
  • Learn offline with Skillshare’s app

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.

phone

Transcripts

1. Introduction: hello and welcome. In this course, you're gonna learn all about assembly language for Intel processes. We start with the 8086 process of I show you how well that works. We use a nice little emulator, emu 80 86 that allows me to easily teach you how processes work on how the assembly works. And then once you've come to grips with that, we move on to more modern processes such as the process of you have in your laptop or desktop, for example, on we start right to send the code for that, we talked with C libraries using assembly, and we also right, Right? A C program that can communicate with some assembly code we've written. So are there really is a lot covered here? You you can become almost an expert in assembly from this course alone. 2. What Is Assembly Language: Okay, guys. So we're gonna talk about what a sandy language is now. In your process, you have what's known as an instruction set. Now, these air basically hard wired circuits to perform certain instructions, such as adding two numbers together, For example. Now, before we have a Sambolin, which people would have to write these instructions by hand or manually now that this was very tedious because instructions our basic binary numbers on there quite complicated on remembering them is very difficult. So that's why assembly language was created on what assembly language is. It's a human, readable way of representing machine coat or instructions in an instruction set. So what we do is we write assembly language. We passes through what's known as an assembler. On that takes are written assembly language that we wrote on a basically just composite or assembles it, I should say, into machine code so that it could be run directly on the process of So once is, once it's once it has become machine code, it basically can just be read directly from the process. Er on the process will start executing whatever those machine codes up, it could be the machine code to add two numbers together, it could be the machine code to call a separate E, so that's where assembly language is. Simply put, it's just a way of representing machine code in a human readable way. You can't run assembly language on a process that has to be assembled into machine code first, much like if you were coding in a high level language, it might need to be compiled first before it can be run. It's exactly the same with the same language. 3. Installing The Emulator : Hello and welcome everybody. Before we can start programming in assembly, we need to actually install a emulator. Now we're going to use MU ADH6. Now we need to install an emulator because it allows me to show you things like the CPU registers, allows us to easily step through programs. And it'll make your learning of assembly language far easier. Without an emulator. There'll be a lot of guesswork attaching special debuggers. And for a beginner, that's just not what you want. So we're going to download a special emulator called MU 1886. And this emulator will essentially emulate Intel processes as they were maybe 20 or 30 years ago. Okay, so the first thing you need to do is go to dragons app.com forward slash downloads, or just go to Dragon zap.com. Scroll down and you'll see downloads at the bottom here. Okay? Now, once you've clicked that, you'll be on the download page for these courses. Okay, and you want to click X86 assembly language program master's course. That'll take you to the downloads that matter. And we just want to click MU ADH6 download. And that'll load the zip file. And just open that up. And we're going to double-click the setup dot EXE, OK to run it. And we're just gonna go next. Next, select the install destination. Mud 86 is fine. Next, I already have it, so I'm going to just override it. Next install. Okay, and then once you've done that, just check, launch the emulator press Finish. And then down here you'll see MU ADH6 loaded. And you can basically write assembly instructions here and emulate them is fantastic emulator. And now that you have that installed, we can start writing assembly language. Thanks for watching. 4. Creating A Hello World Program: welcome. So now that you've installed emu 80 86 we're gonna actually create a hello world program as you always do when you use a new language. So what I wanted to do, I want you to press new by here. We'll just go with common template on just press. OK, now you'll see this, and this is a bit confusing, right for a beginner. Um, essentially, this emulator is kind of running like its own version of M s. DOS on it will load the program. We right here into memory address 100 hex on. Then it'll start executing from there. So when we do ogg 100 page, what we're basically saying here is that the problem we're writing now will be loaded into this address on, and when we assemble, it helps make sure that we offset correctly. Andi, That's why we have to do this by doing ogg 100 page. We're telling the assembler we're always gonna be loaded into this address on because we're gonna be loaded into this address. It should make sure that everything's offset it to that address. So that's what that does. It isn't actually an assembly instruction It just tells the assembler that we're gonna offset from the this little wrecked by here means were returning from a subroutine. Now, essentially, we can give more on this later, but I'll just explain it a little bit. Um, the M s DOS calls us when it loads us. And then by doing Rhett, we return control the Ramos dos. Well, I'll explain a lot more about how this works later on, because it's a bit confusing to understand, right for a beginner. So what, we're gonna do them? We're just gonna first output a character to the screen. Just one character. So I should how to do that? I want you to go. And this is gonna be really confusing. You won't get it all, but just follow what I'm doing because you got to start somewhere just to move a movie page comma zero e h. Now, press enter, and then I want you to do move a l A. And then finally do in Georgia. I mean, I nt 10 page. So if we just press emulate at the top here now, and you run that and just put run and you'll see the A is out, put it to the screen. So if you was the type hello world here, nothing would happen. It would failed. It would not work. So just don't try it. And I'll explain why in a minute Now, this M o. V means we're moving some data to some memory or twosome register of some kind. Now, just go briefly. Explain this because it will be explained much more in depth as we go along. Registers are essentially storage units in the process of itself on bacon store, like a certain amount of data, for example Aah! Construe or one bite on a l console. One bite. However, you can reference them both together using a X. But more will be explained about that later on. So in the process. So we have an eight page register here on a L Register here. On that, their basic just one bite memory units in the process itself. This is not Ram. This is This is in the process of itself. So what we do is we move zero x zero e in a hate So hacks a decimal zero e into a page. And then we moved the character a into a l I remember this. Remember when you when you do when you do a quote like this quote a quote, he gets converted to the binary or bynder equivalent, right? Says the same as saying decimal 65 on whatever. Whatever the binding equivalent is of decimal 65. So now for now, if I m t i m t means interrupt and again here we do 10 hate. So hopefully have caught on by now that the hate of the end of here means that we're using hex a decimal. So zero e h is zero x theory, you know, hacks decimal zero. Now I m t 10 page is basically saying, Let's call interrupt 10 Page Andi 10. Hey, judge is basically responsible for out putting to the screen Now. How this works is will explain much more about this later on, because there's so much to explain. That's why he's taking me so long to even get through a hello world. But don't worry. You just need to follow this through and you'll understand. Now when we go, i n t 10 page were saying calling trip 10 page. Now you Reg to the interrupts in memory, but we'll get onto that later. Wrong. 10 Hate is a bios routine. So you know your by us, right? You probably don't know much about it, right? Because it does a lot more than you realize. The BIOS has its own colonel that can only be used. Um, when you're in something known is really mode, which is a compatibility mode, it basically one year, one year when you first boot your computer, your computer is in a compatibility mode until until until this some code that tells it to go go to the mark, go to the modern architecture. So whilst during this compatibility mode you can do you can run old code like 16 bit code for the old Intel processes from the 19 eighties where, and that's exactly what we're doing here. This is what I m u 80 86 is. It's an old process, right? So in the BIOS is Colonel Interrupt 10 hates is responsible for out putting to the screen. So when we go on do interrupt 10 page, it goes and calls that bios routine and in the BIOS will actually deal with the hardware of getting this on the screen here on basically just puts it into video memory. But more on that later. Because this is quite a mouthful for a Hello, all right. I mean, there is a lot to learn, So I don't expect you to understand all of this straight away. It will take us a while to go through it all. And that's how you print out a to the screen. Okay, so now let's make a program that outputs. Hello, world. Okay, so what we're gonna do to do that, then I want you to go up here at the very top here. I wanted to do Main Coulombe, and we're just gonna tabal this just to make it clear. So Maine is a label. This is how you create labels in assembly you based have the label name, and then a column on you can reference labels all throughout your program, essentially an assembly. Everything runs down. Like even if I put some data here, it would start executing that data. It like the process of runs down downwards, right? If you write it like this without using sections and so on, but that that's how it works. So what we need to do then here we correct main here, which, which we're gonna use and at the very top here. I just wanted to say, um message. So long, D B hello, world explanation Mark quote. And I want you to do, um, comma zero for the null Terminator right to end this string. Now, if you run this, this isn't gonna work very well. Now let me explain why, If you press emulate here and you try to run that you can see unknown office code skipped decimal 65. Now, decimal 65 is the ask equivalent of the hatch character. No, I think that a character, actually, now that he is one of them Anyway, the important thing to know is the the emulator has tried to run this data, which is a problem. So this is what I mean by that. It runs downwards. It's gone in here. It's m s dos is loaded. Our program, it start executing 100 page on its tried to run our message label as actual code. Now, this isn't a variable. Do not make that mistake. When I was first learning assembly, I thought this was a variable like writing like this was a variable. It's not the case. This is no different than our main label by here. The only thing you need to be focused on is DB d. B here means data bytes on it allows us to specify, like allows us to specify a number of characters. Right. So we can say hello world here on that will literally be putting memory as hello world right at 100 hates one slowed the day. So how do we get around this, then? How do we stop it from running our little message here while you use something cold? A jump, You just do jump May. And if you just press that now, you can see it works as usual again. Because what we do is we jump over message here because we jumped to the main label. Okay, so enough of that. Now we can carry on on make our print routine. So down here, just to prince. Okay, on and up here, we're gonna go print under skull shot. Okay, Good. So by here that in operating, I want you to move. Um, s I message on their size. Just another registered, by the way but more will be explained in this later. I'm just trying to your taste of how it works. Then I wanted to go move a h zero hedge. All right, Cool. Now what I wanted to do is is I want to just say Lord SP and I want to go see m p a. L zero. And I wanted to go. Jay. Doc done. Okay on, then, If done is cold, then we will actually return here. Okay, so then I want you to make a new label above here. I just call it, um dot Underscore, Lou, I guess you don't need the under school. Just do. Yeah, I guess you do. Actually. Doing an underscore here dot underscore loop on. Then we're going to say under j dot Done. We're gonna go. J JMP jump dot loop. Okay, so let me explain this. Them 11 print is called. We move our message, the address of our message. I should say the address of our message. Where the address. Because when you reference these labels, it gets the address, right? That's what it's doing is getting the address. So this would be what? About 102 hates, I think, because of our little jump construction. Maybe about 100 three. How much I think anyway, that gotta be the address of message. Right? So we moved on to s I register. Okay. We move as eerie hatred h again, which remember, is our print print character routine. And then we go into a loop here. Lord SB basically loads the first character from message on. Then increments the s I buy here. Okay, So what that does is it load for load the bike from load the bite from from the message, which is hate will increment s I saw on the next time comes around It's pointing a e. Does that make sense? Okay, so, Lord SB it loads it into the air register. I should have said that. So it will read the character and loaded into the ale register, which is one bite size. So then we say compared the a a registered zero. If it is evil, what done? So then we just jay means jump equal. So if a of zero jump to done, we're done. Let's leave on, then. Here we jump back to our loop to carry on So I want you here. Then I want you to say this by here. Copy this. Okay. We can get rid of our print Shaw. Now, By the way, we won't need that anymore. Just place that in there. On, uh, give it a least two on that, is it? That should work. Fine. So rather than dio rather do this than the way I've done this right, you would go cold, prince. But obviously, print print itself specifies the message. So what we'll do instead if we take this out of here, and we put that there instead. Okay. So what we're now saying is his move. Move a message to the S. I register. And then then when we call print than it, it will then move zero hey, h into a hedge register. And Zooey hate, by the way, is I don't know if I said this already. It's the command to the bios. So when we call when we call, like interrupt 10. Hates is for video routines and stuff. Right? So zero here hate is the function number that the bias will look for when we call interrupt 10 page. And in this case, Syria each Zairi. Hey, h means to just print it. One character to the screen. Anyway, Let less run that. Now by President, emulate. We press run and you can see Hello, world. I'll put it nice and easy. Okay, so that's what it looks like, so make sure you get that exactly right. Okay, so I understand that you're probably very confused because this is not like high level programming. And when I first side assembly, I I used to think these were variables like 10 things like this. As I've said already, the most important thing about learning assembly, its first understanding this one crucial point and that is the code runs down, right? It doesn't care if you have data in the way it will run it. It will run it unless your unless you're compiling with sections and stuff. But doing it like this, that's how it works. So without this jump made that the process will come in and it will try to execute page as an instruction, and then you try to execute. He is an instruction. All right. By putting the jump there, uh, this will jump to Maine down here, skipping over our data skipping over our print function because it's all in order. By the way, all of it is in order on then when we call main here, then we can just move the message to the S. I registered the address of the message, not the messenger self. The address in memory which is like 103 hates, I think based on the look of this and then we co print il jump appear, it'll output our message. What it's done, we call wrecked, which puts us online 25 here cause we returned back back to the caller of our celebrity, right. And then finally we call wreck, which passes control back to M s DOS, which ends our program because I I know, I know you're probably really confused. Probably makes no sense at all. But don't worry. This is a hello world, right? When you understand this, you will do anything. So in the following lectures, we're going to discuss a lot of these individual components are in depth on. I'll be using a hello world as a reference to try and explain that how it applies to this hello world program as we go along. So by the end of the course, you'll definitely understand this. Hello World program on. You'll probably had to do a lot more with assembly. Um, you will understand how it all works internally. Okay, so thanks for watching. 5. Understanding The Processor Transistors And Logic Gates: welcome. So in this lecture, we're gonna explain what logic Gates are on how the process of works internally, this is important for you to understand. So you understand how our assembly language is working now, essentially, what happens is on instruction is binary right on. It gets passed through a circuit in the process which results in an outcome on how these how these are integrated in the process is by using what's known as logic gates. Logic Gates are basically the way you position transistors to make certain logic hap such as an and gate on or gate or excell gate each of those gates, two different things. So we're now gonna explain what all of those gates do, and I'm gonna hopefully give you more of an insight of how instruction sets work. Hey, guys. Okay, so I've got a little circuit simulator here on. I'm gonna try to explain how the instruction sets in a process of work, So I'm going to give it to this for now. Uh, essentially in the process, you have lost nose and instruction set. Now, all instruction set is is circuits arranged in a certain way? Onda Obviously they're quite complicated because they there the fundamentals of your process. A call. So you have. Ah, you know, you have circuits such Aziz the Alieu, which is responsible for adding on multiplication stuff like that. Mathematics on our actual instructions also passed through this and said, essentially, when we write assembly and we pass it through, assemble of is converted to its binary equivalent. So I'm just going to make a simple circuit here now just to try and explain some of this stuff. So I'm gonna add a new and Gates she's on. I'm gonna go like this, right? So what the Iron Gate does? It takes two inputs if both the one outputs a one. So let me add in a power source to that. So you can see I've added a power source there, and I've added a power source here. So if we run that now, yes. So if you run that now, you can see that because both of these are on. The output is on. If I turn one of those off, the output is off. Right on off on, uh, often. And I turn this one off. That one goes off on this one number 10 This one off, then it goes off. So the engage base, he says If both inputs are one, then the output is one. So why am I explaining this? Well, think of these things. Here is the data pins on your process, right? Essentially one. It reads. Your instruction in these data pins will be filled with these currents. The these voltages, the current from the voltage, right, so is either high or low. So in this case, we have in this little example I've made for you. Here we have a We have data pins that has to data pins. Right. So what happened is when it loads a bike from memory, it will fill these data pins with the value that bite on. Obviously, they'll be there would be eight of those or whatever it would assigned that the lower eight pins right on. Then it will pass it through a much more complicated circuit than this on. It would figure out which instruction that you are trying to do. So, for example, these two here could be expressed as 11 which equals, um, binary three decimal three. So because because by now we want one equals deaths more. Three, essentially, in this little circuit I made here this tiny circuit. One of our instructions is binary 11 or decimal three. And if you pass in that instruction buying everyone one, we just get out. Put here now in your process, or it's gonna be more complicated than that. So, you know, decimal three, this is just an example Now might mean move, register A l to register a h now. Obviously, we haven't really gone to in depth registers yet, but all you need to know is registers of basically tiny storage inside the process or itself outside of round. So in that case, then you know, decimal three or buying everyone one a scummy represented here. Ah, the current will go in here, Colonel, going here, the output of the one. And then it will start. And then it will go through all the circuitry to actually move the value from the capacitors on move. Evaluated to the other capacities to move the value from from one registered to the other, for example, that's a lot more complicated, but I hope this this kind of makes sense because this is this is how the process works internally, but it is done on a much more complicated level. Andi, there will be a lot more circuitry toe involved to perform some of the operations. This is just a simple and gate to show you that on the lowest level. These are the building blocks, and you would have thousands millions of these in your process it to make it work. Okay, so, um, let me now show you an instruction set and we can go more from there. So if we look by here, this is the instruction set for the 8086 process. Er, this is the we've been using. EMU 80 86. This is ah, simulating this this process, or essentially, so you can see it has quite a few instructions here on in the process will be low to circuitry, like the ones I just did in that circuit simulator. But a lot more of them and more complicated. There'll be a lot of those Teoh so that when it receives the data, the binary equivalents of these instructions, it will. It knows where to route the electricity, the current in the process of which makes certain things happen, right? So, for example, if we look at the jump, construction by here may just take you to that. You can clearly see here. It says on unconditional drum transfers control to another part of the program. So what this does this here would basically one once assembled the binary equivalent. The jump instruction would change the program. Counter register on. By the way, the program counter register holds the value of the instruction in memory in RAM that you're currently executing, so holds the address of where that instruction is. So, for example, in the hello world tutorial, I told you, Emma starts loads us a 100 page. Right? Well, um, in that case, when it jumps to us, the program counter will be 100 hex. That will be the value of it. Right? So what we call the jump here what we're basically doing, we're just changing the program counter register so that it points to another part in Ram. So then, in the circuitry level of your process, the binding occurred of this jump instruction. It would go through all the and gates and all that and all the gates and tell it entail. It gets to the circuitry in the process of responsible for copying the value. Want to jump to to the program counter register. So that's how it works. It's all just clever circuitry, and it is all built on logic, Gates. Okay, so I'm gonna just quickly write a little program just to show you what I'm talking about. Right when I dio JMP dollar, that means to just keep jumping to the same position. It's basically infinite. It will constantly jump back to line seven, right? So it will never end. I just want to show you that this is a nice, simple instruction. My best emulate here. Now you can see here to the right is our assembly. And to the left is Wasim memory at that address. So you can see that the up code for jump JMP It's 235 decimal. So if we now convert that to binary, you can see that 235 decimal is this. Bind the value here. So back up my circuit. Essentially. You see that we have two of those lines here, right? What will call them data lines? You would have eight of those right, And then these values here will be passed in. So if it zero, then it will be off. And if it's one than it will be on right on, then. That goes through all of the logic gates to produce an output like this one here on, then, obviously, where whichever part in the process outputs to it would deal with that operation. So in our case, we're doing a jump, right? And now if we take a look at the second bite here we see 254 which is the sex, which is the value, because here we say, jump 100 page, right, Because when we do jump dollar here, it takes our current address and one of the assembles it replaces it replaces that with, uh, the address that were currently at right, which is 100 hate. So that's how it's an infinite loop, because it will keep jumping to itself forever. Right? But so these two to these two bites makeup that jump instruction, you have the first bite here, decimal 235 binary equivalent by there on what that is is a jump instruction and then the jump instruction expects a second bite, which is where you want to jump to. In our case, it's Children 54 decimal, right? So that is how it works. Essentially, eso If we now run this, you can see it's on infinite Loop. So that's what that jumped is there. But I hope that makes sense about how the process of works because bye bye by explain the surgery like this. Hopefully it makes a little more sense. So when we assemble our our assembly code, it becomes machine code, which corresponds to the instruction set here on By scrolling up, we can see all the available instructions on. There's different variants of these instructions as well, by the way, but you're assembler will choose the right one. Uh, so you don't have to worry about that. Um, so basically, your entire process, er has instruction, said on this is the readable manual, and how the instruction said it's built into the process. Er, is that it's just logic. Gates and transistors, the makeup, different connections on drools of how did of how the data could be transferred along circuit on the uses? A, you know, just use his physics to do that basically, you know, like with the transistors, you can change the way the current flows. So that is how it works. So now that you understand that hopefully now that clears that part of the course up. But you can drop me a message if you get into trouble with that, because it is a complicated subject. 6. Registers In The 8086: welcome, guys. So we're now going to discuss what registers are. So I'm gonna show you how to do that. Now, what I wanted to do is I want to open up emu 80 86 again and we're just gonna go move. Aah! 30. That's all the way to do. I want you to press, emulate and now Rosalyn, press run less press single step, which will run one instruction of time, by the way. So we press single step once, and now I want you to look over to the left by here and you'll see registers. You should see a XB, x e x t X, and so on. These are your registers in the process. Er now, as I've already said, registers a tiny memory regions inside the process for itself, they can usually only store a few bites on. There's a limited number of the, in other words, just to clarify this is not available. There's no variables and assembly. If I was, if I was to try and invent my own, such as II or something like that, that's not gonna work. When we go move a page, we're saying, Move 30 Moved decimal 30 into the A page register, and there's a limited number of registers they displayed here on the left. So what I'm gonna do, I'm gonna just press emulate again Now that I've showed you that and I'm gonna press single step once looked to the left here at our registers we see the a X register, right? You see? Hey, H and L. Now what is Haitian? L This just means high and low. The high bite on the low bite Essentially the a h on the A l registers how builds the X register. So essentially, when you when you talk with a page, you're talking with the height, the high bite of a X register. When you talk with a l, you're talking with the low bites have the X register. So looking back here, then you can see that the erect a X register is only two bites, only two bites. Now, when we do a l, we access the low bite of the X register. That's what the L stands for. When we do a hey h, we access the high bite of the X register. That's what the hate stands for now a x is a register in itself. So if I was to go move a x zero x f f f f on press emulate now if you press single step so it runs. Move A l 30. It'll move decimal 30 into the ale register on. By the way, in case you didn't notice, these bikes have shown here is Hexi Decimal, which is why we see one e on, not 30. Now I press single step again. You'll notice both a hate on a l have changed f f f f because a X is what holds a hater. Nao. Right. So if we assign a X to something, it overwrites both h and air with the value. If we only assign h, it'll only affect the high bites of the X register. So just to clarify here we moved decimal 32 a l Here we move Hexi Decimal F f f f on that. That the hex decimal numbers represented by zero X and start by here. Right. If this wasn't here, it wouldn't compile. It would have to be a decimal number right now. Lex, under here. Let's do move! Aah! And we're going to go see you X 30 right? So another hex decimal number. Press emulate Press single step. We see thirties move to the L Register, which is the low bite of the A X register. Right now 30 is represented by one E hexi decimal press single step again. We can see both h and A L over written with F f and FF and that's because we assigned the full register a X because, remember, X holds a h and l right by moving a hex s move eight x overwrites both h and L because a Haitian a l make up a X hope that makes sense. Remember, l and H low bike high bite Have you press single step again? You'll see that our low is still FF but are high has changed a hex 30 And the reason for that Because here on line 11 we change the A page registered to zero x 30 x decimal 30 right that the low bite stays the same because we haven't changed it Likewise, if you change this h two a l impress emulate single step again single step again Now we're back to ff ff press single step once more now, in this case, the high bite is still FF because we we set the a X registered f f f f online 10 here but because we single stepped here on line 11 we changed a our registered a zero x 30 which changes the low bites of the X register to hex 30. But the high bite, it's not changed, which is why it is still FF. So that's kind of how the register system works on the 8086 process. Er so you have a lot of other registers you can work with is well on. By the way, each of these registers is used in different instructions, so certain instructions will rely on different registers. So, for example, the Lord SB instruction Let me just type that out so you can see it a lot. SB this here if you remember correctly, it loaded a bite from our from our hello world message Right on. Then it's stored in a l. So Lord SB uses the X register right? Because when we do Lord SP, it loads the bike from wherever the s I register is pointing to it loads that bite into the low bite of the X Register. So that's important to note that we use different registers for different things. For example, the C X Register is mainly used with counting operations, but we can get into more about that later on. I just wanted to get a grip on how the registers work first. So we've worked with the X Register less work with the BX register. So I wanted to do a movie. Be X. See you xff zero x f f f f So four X right. So what? This does he moves the hex decimal value f f f f into the bx register So if we emulate that now press single step you can see the BX registers High bite is now FF on the BX registers Low bite is now ff Likewise If you just like when you use move h move a all you can do bl or be hate. So if we do move, be hey h o u x 30 and you emulate that press single step first single step We can now see that the high bite of the BX register has become 30. If we did b l, then the low bike would become city 30 Hex. By the way, guys on likewise, you can do C x ch NCL dx dy h on dio So that's how old that works. So you'll also notice a lot of these other registers down here Now, these these air special registers because they don't work in the same general purpose way as as a XB x e x t x do Now you don't need to worry too much about these yet because they we need to cover them later on because I need to teach you a few things before you can understand them. But I'll go over it briefly. You remember I talked about the program encounter in one of our lectures. The program counter. Sorry. While that in the 8086 is represented by the I. P Register, the I P register contains the value of the current address you're executing and memory. So the process and uses the i p register to know which instruction to load from ran. Now you'll also notice D S E. S on SS, and so thes air segmentation registers segment registers. We can discuss those mawr later on. It's basically allows you to offset in the 8086 you can only access up to one megabyte of memory. But obviously our registers, you know that there are only 16 bits wide, two bites, so they can't address the full megabyte. So we use something called segmentation to access the full one megabyte on. We make use of these second registers here to do that, but Mawr will be discussed on that later s p is our is our stack pointer. Um, again, you need to learn what stack is before. I can teach you that. So that covers registers. I hope that makes more sense. Will definitely discuss more about these special registers here later on. So thanks for watching. 7. Memory Segmentation: So we recently discussed registers and I went over. The segment registers briefly, but this lecture will will go a lot more in depth, will work with segment registers and I'll show you how they all work. So to start, what I want to do is I wanted to go a movie. Ah, bracket by here. I want to dio zero x f f another bracket here and then we're gonna go 30. No, no, no, don't do 30. Do zero x 30. So it's Hexi Decimal says a little easier to read. Um So what we do is we move Hoechst Esmael 30 into address a zero xff or 255 Now, just to show how this works are ready to press emulate, I want you to press single step once Brilliant. And now it down here You will see memory, uh, in view memory and you'll see this Nice a window now here to the right, you'll see 105 Or it might be different number for you. Change this to FF. Impressive date on now. Inside here you can see accessible 30. So we've moved accessible 30 to address f f. However, it is based on our data segment register, which is at 0700 hex. So what basically happens is the value we put here offsets from that from that address. So the way you can calculate the absolute address is by taking our segment value, which is 0700 multiply it by 16 and then add are offset, which is you xff. So that number And that is the absolute address in Ram where this value is stored. So we haven't really set the value at C u X and address CEO Xff addressed to 55 We've said it at the rial address of 0700 hex multiplied by 16 plus 255 decimal. That is where we've said it. So if we was to change our data segment register by doing this move, a X will set it. Teoh, I don't know where let's do a 300 year and then we go move D s a X for data segment on. We emulate that. Now on, I want you to do single step that moves. See, you're 300 into at the X Register here, Two single step again that moves it from a X will copies that I should say from a X into the data segment Register on now, do a single step to make that right And if we go back to memory, you'll see if you put FF here, you don't see the value. But if you now change this to 30300 impressive date you see our 30 hex. So what we've done there, we move where the data segments pointing to so that any rights to any relative addresses will take into account that data segment. So now, as ear X 30 is stored at 0300 multiplied by 16 plus FF not 0700 multiplied by 16 plus FF. But they're the physical address the rial addresses right on. The reason we need this segmentation is because 16 bits or two bites which is the size of all of the registers here, cannot hold the full address that that that too small, which is why we use segmentation, right? So hopefully that makes sense. So what we've done here, we've moved here x 300 into our a X register. We then move the X register when I say move. I mean copied by the way into the data segment register now because the data second registers changed Any right. Sorry we do. The memory will take into account where the data segment is pointing to. So, basically, that is why this is where our 30 years It's no longer at 0 700 with an offset of FF. It is now at 0 300 with an offset of FF. Okay, so hopefully that makes a lot of sense. Now, I know you're already asking this question. Why don't we just do this? Moves your ex 302 ds? Well, if you try that it will fail. And that's because the 8086 instruction said doesn't have an instruction for doing this. Because, remember, assembly language is just a human readable way of writing machine code, right? The process that doesn't have a way to do that. So the assembler isn't gonna put out him for us. You know that's not the whole point. The whole point of assembly is toe mimic machine code on a human readable Let level. Um, so if we was to do move a x zero x 300 then move a X into DS. That is an acceptable instruction. If we did this, there is no option in the instruction set for immediate. It's so that that would not work on when I referred to immediate. I'm talking about literal numbers like numbers that a defined uring assemble time like are zero x 300 by the way, that that is an immediate value. Okay, so if we look at the instructions said use this is a resource because it tells you everything that the that the process that could do it tells you what it can't do. You need to follow these rules because it won't work. You see, it says here the move instruction cannot copy immediate value to segment register should copy the General Register first, which is the reason why we copy it into our General Register X before copying a x two d s. Okay, so that that's basically segmentation. We also have code segments as well. On this. This works the same in the ways the data segment does. What I just explained, apart from it also applies to this I p So remember, the I P is the program counter where? Which instructions? Running in memory currently. So if this is 0000 what it's actually running is this'll code segment multiplied by 16 plus zero. That's the physical address. It's running. So I now want to show you how you can jump to another section of code and what the jump does. Guys, it just roots the execution, right? So, for example, before we do that, let me make a little label here. If I did test and then he up here, I did, um, jump under school. Tests were put in school here, guys, because he would if I did this. All of this does is it changes. The i p i p register 2.2 here so that it runs code from here. Right? That's that. That's all the jump does. It allows me to reroute execution. So now I've explained that they smell wanted to show you. I want to show you how you can jump from one segment to another. It's pretty pretty handy, right? So if I did jump zero x seven c zero and then here I did zero xff, and now we press emulate Onda before we press Emily, let me get this old co. We don't need that anymore. So Chris emulate. And now I want you to single step Jum and you'll see our code segments changed on our P registers changed. So I p register, which is the current instructions being executed is now FF, which is the offset from from the code segment. Right on. Our code segment is now at seven. C zero. So if I quickly opened up a calculator on gonna press hacks here, I'm gonna type seven c zero on. I won't change that to decimal, and I'm gonna multiply that by 16 and now I'm going to click hex again. You can see that gives us seven c 00 fine now, plus FF, you can see seven c f f. So that is the physical address that we are jumping to. And then, obviously the process of will read the value from this address on That is our instruction. It's going to execute 8. The Stack, Subroutines And Endiness Explained: So we're now going to take a quick look at this stack. Now the sack does allows you to store temporary information that you don't plan on always keeping. And it's a very clever concept how this works. So what I want you to do, I want you to go push zero x f f f f. That's all I want you to do. And I wanted to press, emulate on just press single step. And now, once you've done that, you can see that the SP has changed. If you press step back, you see f f f e single step forward now. This has changed F f f c so the stack grows downwards from memory. So when you push, it grows downwards. So what? We've essentially done what? Me press single step. We push the value the immediate value F f f f to the stack at the standpoint of position. So we press single step. We see f f f c. So if if we now go to view memory and just by here, type F f f c, you can see that our value is there. If you do f f f e, she's what it used to be. You can see nothing do FFC. You see that? So that's how it works. The stack grows downwards and we push values to the stack. And then if we pop by doing Poppy X, and we do emulate if you know a single step once you can see this, changes to F f F C if you single step again. This goes back to F f F E and A X contains the value we popped off the stack. So we push F f f f to the stack and then we pop the value back off and put it in the X register. So hopefully you can see how that allows you to have temporary memory, because what you can do, you can set the stack pointer to a position in memory, and then you can make use of the stack to store information temporarily information that you're pop off later like we've done here. So the stack pointer relies on the S s segment. So that's the SS segment is 0 700 which is why, which is why the value is stored in 0 700 f f f c right, because our stack pointer is is that f f f e? So if we was to ever change the stack pointer, the stack would grow down from that position instead. So that's an important thing to note. So you can see by using the pushing park instructions, we can easily push temporary data that we plan on keeping temporarily. Now, calling subroutines actually uses this stack as well. Now, if we if we did ah, jump for example Onda, We have some code here and we want to jump over it. So we use a job now. This doesn't use the stack. This will jump here and will never return. But if you use coal, it will go there. But it was expect to come back. So, for example, if we did, if we did ah, label here will go on a test on. By the way, when you referenced labels when it's assembled against converted to address is obviously because the assembler knows Theodore s that this test label should be at based on the origin here and some other clever, clever position techniques or uses, such as counting the size of our instructions and stuff like that. So if we went here. I will call this Made. Yeah. On main calls Test? Yeah. And here do read as well because we need to return control to the M s DOS operating system . Red returns from separate een call calls a subroutine. So if we now go here, I'm just gonna go move aged here. X 20. Okay. Now, in our test, make sure there's a wrecked by there as well. Okay, because we because we're calling test, so we need toe return from that celebrity. I just wanted to go move a hate zero x 10. Okay, so if you if you emulate that now, I wanted a single step, and you can see that Cole's this address here. Okay? And then that moves 10 single step again. That moves tend to a page, and then we call Rhett to return from the subroutine. So that returns from the 17. So then runs lying 10 because we call test. We returned from the 17 which puts us online 10. Yeah. So then, if we then step through that, then by using single step again, you can see that changes the 10 page in the a hate register to 20 page and then finally return again to give control back to him a starts Right now. The reason I want to show you this is because call uses stack to store return addresses. So I'm now gonna explain how call uses the stack to store return addresses we press emulate again on this summer. I want you to go view memory on. Let's change this to F F F zero, not f f f e I know the stack point is pointing f f f e, but we use FFC were just so I have more to see so I can show you how it's working. So if you no single step on the call you can see it's put some memory in here. 0301 So it's actually stored the return address, right? Send a few single step again and in Retz, it knows where to jump back to because the return address is stored here. So it jumps 20103 and you might notice the's bites or back to front. Why do we see 0301? Well, this is this is a thing called endedness. Now what endedness is its bite order so little Indian will flip the bites. So say we put say we push the value Let's say we pushed the value zero x f f f for it will be stored in memory as f or FF. That's just how they do it. And then big Indian means it will be in order. So if we did f f f or it will be stored as f f F four. So that's very important thing to know about intel. Architectures is they use little Indian little Indian nous now, so you can see that by calling the coal, it pushes the dress that needs to return to to the stack. So, in that way, then when we come back, we call wrecked. It knows where to return to. So that is how all that works, guys. So 0301 is actually 0103 eso then one when we call, read it, the process will look here. It will see that this is the value it will pop it off the stack on. Then it will start executing from there. So that's how subroutines work in the process that this is how we can call things and then be able to get the execution back to us. It's because Cole uses the stack. It stores the address that it needs to run next. So then, when you call Rhett, it pops the value from the stack. Much like we use are pushing Pop earlier on in this tutorial, it pops it from the stack. It starts running the CO from there, So that's how several teens work. I hope that explains how the stack works is very handy, Andi. It's pretty much necessary in all modern processes when when you write a program in see, for example, and you have loads of local variables, they rely heavily on stack toe. Be able t stall those temporary variables for you because, you know, when you leave a scope in C in the C programming language, all of those primitive variables like intra jersey charge, they'll get removed, right? Well, it's thanks to the stack. Why that's possible 9. Moving Data To And From Memory: So in this lecture, I'm gonna show you how to read to and from memory. Eso makes you remember the data segments we spoke about in segmentation. Because any address, we off several offset from our segment. Right? So let's put some data in in in address zero x zero. So just go M o V for move. Teoh this bracket here, zero x 00 This bracket here now, just 2 30 0 x 30 Will do hacks. So if, you know, run that on. All I wanted to do is I want to press, view memory. I just set this here. The one on the right. Dizzy was he was U zero. Yeah, so we can see currently there is CD of this location. If you're now, press single step, you can see that's changed. 30 hex. Why is it why is it change to 30 hex? Because here we say, move hacks decimal 30 to address syrah zero, um, to address syrup. So how that's working is if we go to our emulator, you see our data segment facets 0 700 So this zero x 30 is actually being written. Written address, CEO, 700 hacks multiplied by 16 plus offset, which is zero x +00 The address were signing. That is the physical address that is being set. So I've just showed you how to set immediate addresses, an assembly. But what if you wanted to use Theodore s from a register? Uh, you want toe target? The address of a value in a register. So the value and the register is the actual address. Well, you can use the bx register for that. So what I want you to do is that wanted to go move bracket B X, and then we're gonna go zero x 30. Okay, And now in here, we're going to set the x 20 X um, FFC room FXC room. So this will move hacks 30. So the address CEO xff zero. And obviously, because we're saying Theo, the let's target the value in BX and use that as the address. This could be changed a run time. So whatever the value be X is when this instruction is run will be the address we write to . So essentially, in this case, because b x zero x f f f zero we are right in zero x 32 Address zero x f f f zero So you just press emulate there. We got a memory of you again, Andi. I wanted to put f f F zero in here so you can see this is the memory is gonna write to write, Just press single step press single step again and you can see it is just written the bite zero x 30 into address f f f zero Because the BX Register's value is f f F zero on in our move instruction here, you can clearly see that we say we want to write that the value zero x 30 into whatever the BX value is holding. So BX register holds the value of the address that we're going to be writing to. I hope that makes sense now. I want to show you a problem, and I want you to see this because you need to understand this. Remember earlier on in other lectures, I explained to you that different registers two different things. Well, be X is great for this sort of thing. If you was to use a X try toe, try to emulate that there's an error. That's because the instruction set of the 8086 process. It doesn't allow for this, in other words, inside the 8086 process. So there's no circuitry to allow you to use the X Register in this way. You know, all the transistors and stuff. There's no path for that toe work. So that's in the hardware level. So we use B X for doing that type of operation on That'll work. So I now want to show you bite and word. So essentially after arm of instruction, here are move instruction. If you put bite just like that, then what we're saying is we only want to write one bite. But if you put words, it means we want to write two bites. Now this this is for the eight awaits six. A word will be bigger depending on the process of architecture. So just to demonstrate this firstly, I want you to dio bite on, just press emulate. Okay, So if you open the memory of you, we're gonna go to address f f f zero again and just single step single step again. You can see it only changes One bite. Now I want to show you something else. If we change this to a word and I want you to press emulate again okay. On back to our memory address. FFC rope. I wanted to do a on. We're only doing this because we want to be able t o be able to tell the difference between the memory because they're all zeros. It's going to be difficult to see what's going on, right? That's why I'm doing that. Uh, okay. If you know Chris, single step single step again, you can see that it's now changed to bites. Even though we only assign one value here of FF because we used word. It takes two bites on the other bite is a zero. So I'm now going to show you how you can read data from memory. Let's try this. A movie a X comma, zero x 00 futures price Emulate Andi, I want you toe go to the memory view again by going to view memory. I just changed this here 2000 and you can see that CD is by there. OK, while CD 20. Now, if you press single step, you can and you now look at the X Register. Here you can see 20 CD so it successfully run it successfully. Read that data from address you X 00 Now if we was to just to do pe el and we press emulate rather than a X on we single step, we can see the only CD is red on that is put into the low bite of the X Register, the A L Register to change that a h and you press emulate. We pressed single step. You can see that the same CD is read from the address, but put in the high bite of a X. But by using a X impressing single step, it loads a word on. If you remember, I talked about endedness on the Intel machines, a little Indian. That's why the bites are loaded in here, back to front. That's why we see 21st and then CD. That's what happens when you do word operations on a little Indian machine. Now that is how you can read data from memory, so this could be addressed, Um, 01 on. Then it would read from 0 700 multiplied by 16 plus CEO X +01 that would be the physical address of a breach, which is gonna be 20. So if we press single step, we see 20 in low. Hi. Is 00 because the third bite is your zero. Likewise, we can actually still use the BX register to read from the addresses as well, so we could pass in f f F zero here like before on then we put the X here, press emulate and now that will read the address from whatever be excess pointing to. So if we go ff zero here we can see the bite, Cyril zero. So let's just change them to something so we can see that this works on If you know a single step, you can see the X register is now a So that is how you read on right in assembly to memory . So essentially, our M o V instruction can be used for transferring information data between registers. Andi memory 10. Interrupts And How They Work: welcoming in this lecture we're going to discuss interrupts now if you remember from our hello world tutorial, we did this the output, a character to the screen. And if you just emulate that press run, you can see a nice so a character as I put it to the screen. Now what we're gonna be explaining is how interrupts work on how to create them. Now one will use I nt that signifies we're gonna interrupt the process on what? This will do this. Interrupt the process, er run some code and then jumped back to us a little like when we make the Cole. What a little like when we use the Kolkey, where when we make subroutines, right, it's a similar sort of set up. What happens is when we go in ST zero x 10 it finds the address in memory that interrupts you. Extend, it is half should handle on. It will jump to that address and start running that coat from there. So the best way to explain this is to press emulate, and we're gonna open up our memory, view, view and memory. I just went about 00 here and put 00 here. Now, all of this data you see here is called the interrupt Vector Table on what the interrupt vector table holds is 256 different addresses corresponding for each interrupt. So when we called zero x 10 it goes into this table and it finds the offset 40 x 10 and it will take the address from here and then jumped to it because this information you see stored here are dresses corresponding toe weather in corresponding to the memory where the code is for this interrupt. So by changing these addresses, we actually change the code that is run when you call an interrupt. So just keep this single less coal interrupts you X 00 right, Just best emulate. And I want you to press single step. Make sure a single step press it again. And then finally pressing one small sore runs the interrupt and you can see the address where act is F 40001 70. Right, So this is the segment on this is the offset. Remember for the physical address, we take the segment here multiplied by 16 and add the offset and that is the physical address and ram where this code is Now we go back to our memory of you. Let's compare this. We see a four here and we see zero. Here we see 01 here and we see 70 here. So these four bites make up the address for interrupt zero. And now these other four bites here 1234 They make up the address for interrupt one on 1234 Those ones make up the address for interrupt to on this goes on and on until interrupt 256 . So I hope that makes sense. So what we can do, then, is by changing these addresses, we can change wherein. Interrupt goes now, Remember these air store back to front because little Indian flips the bites when we store words. Okay. Now, because the interrupts are handled in a word way, this is why they are flipped. So, really, this'd is 01 70 for these two bites on. This is F 400 for these two bites, so you can see that the offset is stored first for an interrupt on. Then the segment is stored second. So these two bikes represent the offset, which is 01 70 on these two bites represent the segment, which is F 400 And if you look at the address after we single stepped into that interrupt look at the magic, you can see F Fours years, years. The segment 01 70 is the offset. So if I just get up, no pad quickly, we see 70 01 So this is actually 01 70 right? And then we see zzz wherefore? Which is actually F 400 So combining those two we get the address on the physical address would be F 40 zeal multiplied by 16 on. Then we would finally plus 01 70. And that's the physical address. So that is how the interrupt when you call into a zero. That's how it knows which code to run when you call Interrupt. Zero. Because it goes into the center of Defector Table, which is stored at address you in ran on holds 200 fixed six inches at 256 interrupts Sorry . Each interrupt entry takes four bytes, the segment and the offset. So the first, the 1st 2 bites of the offset. The 2nd 2 bites are the segment. Okay, So great. Now that you know all that, let's make this interrupt point to us. That should be fun. So back to our code them. Let's scary to this. I'm what you gonna do is you're gonna go your first gonna push the data segment to stack, Okay? Because we're gonna need to change this value. We want to restore the data segment later. So he popped by here. Okay, So remember, by pushing to the stack, we can restore there later. So we pushed the value of the DS regs register, which is the data segment. And then later on, when we pop, it restores that value. Okay, so what we need to do now, then we need to change our data segment to point to the interact vector table so that we can offset to each individual interrupt entry. So to do that, we go move a s a x zero move D s ex. So while this will do the move zero to the X register and then move the X registered to the data segment. So at this point, anything we do to that anything we do relate into data on a memory well offset from address zero in physical ram. So let's now go to our memory of you again. I once more than we can see the offset is the 1st 2 bites and in the second comes second. So the offset will be to our label in our program. So let's make a label for handling this interrupt, go into here and do we'll call it handle? Uh, I in t zero. Yeah, are now in here. I wanted to do move a h zero g hick zero e h move a l a. And we're just gonna output on a character to the screen right now. Much like one we want to return from separate. And we use Rhett to return from an interrupt. We use I rat. So use Iraq here to return from that interrupt. Okay, great. So we're gonna make it, so when you call in trip zero, it runs this little subroutine we've written here. So back inside here, then just above popped es. I want you to actually move the address of this label here where the address it will be when it's assembled into the 1st 2 bites of address you x zero. So because we pointed our data segment to address zero anything we officer, he'll will be related to address zero. Right. So if we do move, you open up your brackets, that zero x zero, okay. And then I want you to do handle I am t zero. Okay? Now, I want you to press emulate. I'm when all tenure. I just want to demonstrate this. So if, you know, press single step, that pushes our data second to the stack because we're gonna want to restore it later to what it previously waas we then a single step again that move zero to the X register. Single step again. That moves a X to the data segment register, which overwrites our data segment with zero. Which will mean that when we access the relative address here, your x zero, it will offset from our data segment, which is zero on because we've pointed our data segment to address zero on our on our offset is your ex 00 It should allow us to change the first biting ram so and oppress emulate again quickly, cause I just change that. Okay, so good. So now we're at the final instruction that actually moves the address of handle I n t zero ar label into theater effect the table. So if you're now press single step, you'll notice that it's now become zero Easier one. Now, we still have not changed the segment that this should offset to, so we need to change that. Next. If you look here, our code second register is 0 700 So we can use that register to overwrite these two bites . So let's do that now. So this this series you at fault should become 00 uh, 70 Right, So less. Now do that. We're gonna go in here, go move zero xy or two. Because around these two bikes ahead for the segment on, we're just going to go see s for code segment. Press emulate. Good. Now, if you press single step, single step, single step, single step, that changes that on now. Do single step again and we can see that's now becomes ears using or seven. I think I said 0070 Earlier, I meant 0007 which is which is correct. And now a single step again. That'll pop off data segment. Our data segments now return to 0 700 which is what? Which is what should be. And then we return. So at this point, we have changed into a zero. But now we haven't cold interrupt. Zero. So what I wanted and I would do underneath Pop ds, I want you to just do interrupt your X 00 Ah, Now that'll call interrupts your X zero, which is our routine here. So if you know, press emulate. If we just press run, you can see a has bean out, put it to the screen. So that worked successfully. So congratulations. You just created your own interrupt. Now, let's do it. Have been more slowly. If we press emulate again, we're going to step through it so you can see what happens. I'm just gonna single step up until the interrupt whereabouts called the interrupt. Now we single step, we can see that has jumped to our code in handle in it. Zero, and it knows where to jump. Because if we open up our memory table again, change these both two zeros, we can see that these four bites here 1234 describe where it should go. We can see these two of the segment, which which is represented here, and we can see these two of Offset, which is represented here on the right. So that is how interrupts work now changing interrupts in a modern process is a little different once you go into protected mode. But that's more of an operating system development type of thing, which won't really be discussed in this lecture. So you can change interrupts here because we're running on 8086 If you try to change the interrupts while running an operating systems such as Windows or Linux, you probably won't be able to do toe memory protection. And also they have something a little different than an inter effective table. Uh, but that's how you curate interrupts in the 80 wait six. So congratulations one you call in it. It acts. Is it kind of access submitting? But it's not quite the same thing. It interrupts the process. I'm runs this code because we've overwrite interrupt zero with ours. So let's say you wanted interrupt you Exeter one instead of zero x zero. Well, let's change this change this to Xerox here. One on this here becomes four on this becomes six. And now, if you now emulate that, we're going to step through it so you can see what's happening. Look at the memory view as well. We go single step, single step, single step, single step. You can see it's changed that bite there. Single step again. You can see it's changed that one on. Now, if we just press run, we can see a So that's how you change that? Because thes four bites 1234 are interrupt. Zero thes four bites 1234 are interrupt one The's four bites. 1234 Interrupt to on this goes on and on and on until the inter effect table ends. So I hope that all makes sense. Guys is a nice, handy feature in the 8086 process. Er 11. Talking With Hardware With In And Out Instructions: So I'm now going to show you how you can talk with hardware on your computer using assembly . Now there's these two instructions in the intel process I called in and out on these allow you to send data to the hardware on on your computer. Right. So just to demonstrate this press emulate on, you'll see virtual devices here. Click click Printer don't yet see. And this says that the data port is 130 decimal. So if we out some information to that port, we will see that the emulator will show us some characters by here. So we first want to move a character to the A L Register. Let's just call it a And now we go out 130. Make sure it isn't Hexi decimal guys because, yeah, that is said 100 3 decimal 103 D, right? So 130. An impasse in a all there. And now press emulate press run and we can see nothing happens. That's because my virtual devices closed. If you open it again, I am pest run and we can see that it's output it A to the printer. So we've essentially talked with our virtual hardware. But in in real life you would talk riel hardware such as a hard disk. And you can read sectors from it like that and so on. Now, you only really need to worry about these out instructions if you are developing kernels. But it's best to discuss them anyway. So you understand how all this works. Okay, so now let me show you how you can read data from a piece of hardware press emulate again, and we're gonna go back to virtual devices. Just press simple dot dxy. Now, this is a simple program. These guys emu 80 86 have developed to allow us to test i o operations. So inside this right bike to put woman's ear, just just type 20 and we can see if we read from If we re from Port woman zero will now get 14 x decimal. Right. So let me show you how you can do that. All you have to do go in here, go in and do a l 110 Now just press emulate. And now, if we single step, we can see that a L register has now become fording hex because it's red from that port in simple don't yet. See? So this is exactly how communication with your heart dis works with these in our instructions. Like I said, you won't have to worry about this unless you develop in kernels. But you know, your colonel use Iot operations to talk with some of the harbour on the mother board. Onda also other things such as your hard disk. So help that makes sense. That is, in our instructions, they used for talking to hardware. You don't have to worry about it unless you are developing Colonel stuff are kernel modules or developing a colonel from scratch. 12. Mathematics Adding, Substraction, Division And Multiplication: Okay, I've gone back to the instruction set, and I really recommend you download this guy's because it will really help you just search for 8086 instruction set. PdF. And you can get this one that I'm looking up from. Gabrielle. Uh, whatever. That domain address is up there. Uh, but anyway, it has everything we need for the eight. Await six instruction said it represents every single instruction in this process er on how to use them. So we're now going to explain mathematics in the eight awaits. Six process er, you can clearly see the add instruction allows you to add registers with memory memory were registers registers with registers memory with immediate it's on registers with immediate It's so if you look at the algorithm upon use an add instruction operandi, one will equal upper and one plus upper end to So In this case, when we do at a L minus three op around one is a l is the A. L register on it becomes a l minus three. Okay, so let me show you how you can do this. Then we go back to emu 80 86. We're going to go move a l 20. We're going to go. Adds a l 10. If you just press emulate on. I wanted to single step so we single stepped once on now the air register is 14 hex single step again, and now you can see the ale registers become one e hex. So we've added 10 to 20 essentially on one years the hex decimal equivalent off 30. So that's how the ad works. And in, obviously weaken Go minus five here on then, and an ale will become 15 If we single stepped ale Redd's becomes hex, fording or decimal 20 single step again. Now it becomes hex zero F, which is 15. So you can see that by using mathematical instructions. This way we can add, subtract, multiply and divide our registers on memory and so on. So likewise. Then let's now use the subtraction. So if we go subtract a l minus five, a. L will become 25. If we single step, send the step again. We can see that Ailes, now 19 hex if you open up your calculator, said it's a programmer mode on. We put 19 in here on our press decimal again you can see it's 25 because we're subtracting minus five from a L. If you did five here on no, a negative number, then subtract five from mail, we get 15. So that's subtraction, guys. Now then, back to our instruction set. I've got up multiplied The multiply instruction for the eight awaits. Sexier. You can see this is an unsigned multiply. So if we was toe want if we wanted to do a signed world supply would have to use the i m u l instruction. So? So this this Mun instruction will not work with negative numbers, guys. So don't use it for negative numbers. Use I am ul instead because this is an unsigned multiply. So how this works, then the algorithm is a X equals Ailes multiplied by operate. And if if we are multiplying a bite If if the operandi is a word, then this is the algorithm here a x multiplied by operate and Andi It sets the d x toe the high two bites on the X to the low two bites. So let me show you how this works. Then on we're just gonna multiply this'll by 20. So what? We're going to do? We're going to go move a l 20 When? Ago. Move bl 20 and we're just gonna go multiply B l If you know, puts emulate single step. You can see a l becomes 14 hex. Single step bl bl becomes 14. Hex single. Step on. We can see. The result is 01 19. If you go to your calculator, make sure programmer Moz selected Go to decimal. Do 20 times 20. We get 400 which is 1 90 hex. If you check back here, we can see the high bite for the X Register is year one. The low bite is 90 so that result is correct. We have essentially multiplied a l by Bill. By doing this, let's check the algorithm again and you can see a l most applied by operate. And when it's a bite in this case, it's a bite. So if we go back to any ready 86 we move 20 into the oil register 20 into the bl register. We do more emu lbl, which basically multiplies ale by bl which equals, uh, 1 90 hex. Okay. And that is 400 decimal. So that's how you do multiplication. So let's now do multiplication with bigger numbers. I want you to set a x 2 60,057 B x 2 20 and just to multiple multiply be X. If you now press emulate single step X becomes 15 A are single step B X becomes 14 hex Single step for the multiply X becomes be 1 90 that be 198 Sorry, DX becomes 01 So both of those registers contain the result here. So for me to demonstrate how they both contain the result, go to the hex editor. We're getting a tie at the hex calculator side. We're gonna type in 01 Make sure. Heck selected guys, Andi. Then we're gonna type B 198 and we see 11,000 decimal. So if we waas to do that calculation manually, 5550. Make sure decimal selected guys multiplied by 20 equals 11,000 one B 198 So you can see that when one we will supply with their words. IE two bites. The D X Register stores part of the result, and then the X Register stores the remainder of the result. I hope that makes sense. So now we'll discuss sign multiplies. This is used with negative numbers. So you can see when we do negative multiply here, we use I am UL. So I'm just gonna copy that in so that you can see just to say some time. So if we paste that in there, you guys compose if you need to. So we move a l we moved minus two to a register minus four to the BR register and then we do assignments. Play on BL given us our result. We know press, emulate press single step A l becomes f e because its a negative number. Andi, As you might know already, one a signed number is negative. The highest, most bit is one. So, in fact, is to demonstrate this If I open up my calculator and I type in f e here in the hex, you can see that the highest bit is one here, right? So that represents that it's a negative number. I assume you understand signage, if not look that up because that is not covered in this course. But essentially signed numbers have you know, because it's showing us this in hex decimal form. That's why it looks a lot bigger. It's just the way that you represent a negative number of memory because processes don't have true negative numbers, right? Use that. Use the binding use. You arrange the bits differently to represent the negative number. So we single stepped. Now we CFC in bx every single step. Now we do a sign multiply. We can see that the result is 08 which is correct. So I know I said I wouldn't discuss the sign numbers, but I'll briefly go over it just for those who have no idea about the sign numbers. If you change this, my studio minus one and just press emulate single step, you can see that that is now FF, which is 255 decimal, right? If you do minus two right single step, you can see that snow Effie do minus three. Emulate single step to see. That's no F. D. So essentially what? 11 numbers negative one. We're working with signed numbers. It starts from from the highest point, and it works backwards that that's how you know that it's signed by using sign numbers. You also lose half of the positive range because it needs to make room for the for the negative number. Right? So that's how it works When it signed and we're using negative numbers, it basically works backwards. So minus one is ff on so on. But I stress reading on that further if you still don't understand. Okay, so we're now going to discuss division. You can see that the algorithm is here when the operation is a bite. Then the the equation this run is the a X rays two divided by the operator and on a l will equal the result. And then a hate will be the remainder of that division. So let's now try that out. Open emu 80 86. We're gonna go move X 20. Move bl 10. We're going to go d i v b l If you now press emulate single step a X becomes 20 hex single sap feel become zero A hex single step the divisions done. We can see that 20 divided by 10 is too. If you get your calculator up 20 divided by 10 is too and we can see a hey h a zero. Because there was no remainder from that division. Likewise, if we go back to the instruction set, you can see that one will use bigger numbers. When we use words IE two bites, Then it will set the full X register to D x, a X, divided by operate. And on then the d X work registered will then be the remainder of those two. So let me show you how you can do that then. So I've briefly changed the code here just to represent how this works. So DX become zero hex X becomes f f f f x bx becomes 400 decimal. So just to demonstrate will happen here. These two will be combined so it will be zero a f f F path divided by 400 decimal right on . Then the result will be stored in the X register. So if I just press emulate here, I single step dx become zero a hex. I single step a X becomes f f f f I single step be expert, comes 400 I single step on, we can see the result is 070 a. So if I just get up to calculate to demonstrate that then I'm gonna press hex in here. I take a f f f f all right. I click decimal here last 7 20,000 I divide that by 400. Press enter. Go back to Hex. We can see the result is 70 a, which is our result here. So it so the the instruction set basically requires DX to be the higher end or than the higher end of the number on X to be the lower end of the number. And then it will perform a division on those based on the in our case, the BX Register, cause that's the operation we've provided. So it divides this number by 400 decimal and stores the result in the X Register. If we go back to the pdf document, we can see that the DX register will hold the remainder. Now, if we take a look at the sign division, it works. Exactly The same is multiplication. So I won't rewrite it out for you because you know what to expect with that. Essentially, when we use the negative number here minus 203 on the BL has four, then we just do a sign division on both of those, and you can see the outcome here. Based on these assembler comments, the ale register becomes minds 50. A hate register minus three and oversee the H is the remainder here, and the air register is the result. So there's something I wanted to show you about the division, which is quite important if there is a mathematical areas such as divide by zero, which I just wanted to do. Now I'm gonna set to be X rays to zero here. I'm gonna press emulate. I want a single step through it until the dividing A single step. Now you can see that there's an error. Here it is transferred control here. Toe handle that error. Now. This isn't interrupt right now. If you remember, interrupts lecture, you can change those interrupts in that table toe handle division areas for you so you can change the interrupt point to you. So won a division error occurs. Maybe you can output a message to the screen or whatever saying divide by zero error. So that's an important thing to note that the process itself actually calls The's interrupts when certain events happen, such as the division era. If I just press run to let the program finish, you can see that the emulator is telling us to change the address of interrupt zero in the inter vector table to our own address toe handle a divide by zero error because that's what interest zeros used for. If there's a division error or something goes wrong with the division, then interrupt. Zero is cold by the process itself. So by overwrite by overriding that, interrupt your own handle, you can handle division errors manually yourself, such as out putting a message. 13. Condition Instructions: so I want to teach you about conditions. And when I talk about conditions, think of if statements in high, high level languages. So if this then do this, I should have driven assembly. So you stop the condition with a compare instruction. So you do something like CMP ale, register Beal register. Right. And it will compare those two and set these flags based on how it compared them. So I'm now going to show you those flags. So for me to show you these flags, I just want you to open up any your 80 86 press emulate. And now you'll see this flags button down here. Just click it. And these are the flags, right? So you have, like, the carry flag zero flag on so on. So on the compare sets thes based on how it compared them right, based on how it compared the two results so more on that later. But now that I showed you compare, I want to show you J j instruction. So if you type j here, this is the jump equal instruction. So how this works is if the zero flag is set. If if zf is equal to one, then jump to the address she provided. So if you look at this example, it says Jay, label one. So jump here. So when you call the what? When you use the compare instruction here, it compares the ale register with decimal five now because because the these match it'll set zero flag, toe one the compare instructional Do that and then the jet, the J instruction, the jumpy equal instruction will simply check if this year of flag is one. And if it is, it will jump to label one. So let let's just do that ourselves just so I can demonstrate this. Go to emu 80 86. Well, we're gonna do We're gonna go move ao 10. And I just wanted to go compare a l 10 and I want you to do Jay under scroll equal. All right, down here will define that. Um Andi, I just wanted to go move a h zero. He hit zero. Hey, h move a l a inches e x 10 Just You can see that it allowed Cut A If that is valid on, obviously when we do, it interrupts your extending. Here. This is the bios interrupt for video operations. Zero eeh h is the function we want to call in our case. Output one character and then the A L register contains the character we're gonna output. Okay, so I wanted it down here. Wanted to do another label calling, except on school exit on just under the J Aegis to Jum JMP under scroll. Except so now let me explain this to you. We go in here, we move 10 into a register. We compare if the ale register holds the value 10. If it does, then the ZF flag is set right now. J e l checks If this ZF flag is set on, if it is, it'll jump toe that address that we provided here, in this case, the address of the equal label. So if you just press emulate on I wanted to open up the flags as well. So you can see this happening currently. Weaken. See ZF zero. Right. I want you to go single step now. A l has 10 in it. A hex? Yeah. Zero hex press single step again. So runs the compare instruction. We can now see that zero flag has changed to one. Okay, Now what? We press single step again. That that the jump equal instruction, uh, is going to actually check for this era flag on? Because it's there. It will jump to here. Now you can see in the disassembly here. This is Jay Z. Now, the assembler is quite kind with how you can write this, because it has a bunch of aliases that points of the same instruction. So Jay is the same as doing Jay Z. Okay, so, you know, jumped zero basically jump jump If if the if the zero flag is set right, the red flags set. So if you press single step now, you'll see that it is now running our coat output to the screen. So I just press run now we can see a is output it because, um, a L is equal to 10. So we jumped to the equal label by here, which runs this code. Now, if you now change this to if you know change, they'll tow 11 so it doesn't match and just press emulate. I went a single step ale becomes 11 0 XB Xerox syrupy press single step again. And now if you press the flags again. You'll see that the zero flag zero this time because our compare instruction when it compared ale register with 10. It didn't match because the air register has 11 not 10. Okay, so if we best single step now, you can see that it just carries on executing it didn't jump to that label because zero flag wasn't said right. So now the next instruction is our jumped to the exit routine. So we press single step Now you can see that the next step is to just return back to M. S DOS. And there we are. Programmers return control to the operating system. So what's happened now is that it's no longer output it because a L is no longer equal to 10. Let's now discuss jump not equal j any this instruction checks if zf flag zero and if it is , it'll jump to that label so it does the opposite of jump equal. So if we go back here and we say j any instead of J and now you run that press single step ao become zero B that gets compared. If you single step again, press the flags, you can see the zero flag zero press single step on. Now that jumps to the label, ready to output our A because the zero flag zero. Because when we used to compare instruction, a l does not equal 10. So the zero flag is never set. Let's now look at the jump above instruction. J A. If you go on, take a look here. If the carry flag zero the CF flag on the zero flag. Zero. There's a ZF flag, then jump. So if we go back here on, we say J a equal. So if a L is above 10 then you'll jump their free press emulate. Press the flags, press single step single step. Now you single step again and it will run that on the reason it runs. That is because the CF flags ear on the ZF flag is zero. Likewise, you can use the JB instruction jump below instruction. And if that this means that if the CF flag is set, then it will jump. So if we go back to here on, we changes to G J B equal on. Let's change Ailes. 15. Emulate press flags. Press single step press single step. Can I see the CF flag is one press single step again on it will output a to the screen. Excellent. So we also have instructions such as J J A. E jump above equal. So if it's a bubble recall, it'll jump, and we also have jumped below equal. If it's below equal, then jump so you can see by. By using these instructions, you can help control the flow of your program. 14. Reading bytes with the lodsb instruction: Okay, let's not talk about the Lord sp instruction. If you remember from our hello world example, we made it so that we can output hello will to the screen. And we use the Lord s B instruction. So what this does it loads a bike from memory and then either increments the S I register or Decca mints it based on this flag So that, Sir, if the DF flag is not set, then it will increment the S I register. Otherwise it'll deck prevented. So let me show you this In practice, let's go to emu 80 86 and down here. I wanted to make a label. We're gonna call it message. I'm gonna go db for data bike. Hello, world. Yeah, eso that I'll just put hello world into memory at this address on it Lost have annulled Terminator If we now do m o V s I message right? And then we then go lot sp I just want to press emulate. Okay, so if we now a single step we can see the s I register points to our message 0105 hex. Best single step again. You can see that it's read the first bite from that data. We now have 48 hex or character Hey, H in the low bite of the X register. And if I just set back again, you can see that the S I read store was 105 But then when I single step into law SB it becomes 106 So that's what it does. It reads a bite from memory at wherever the s I registers pointing to reads that bite and then increments itself or deck Ament itself, depending on if the flag settle not and that is how it reads your message. So every time you call Lord SB, it will read the next bite. It will read the bite that s eyes pointing to and then it'll incriminate site. And this is great because it allows you to easily iterated through character raise very, very quickly. Obviously, you never raised an assembly, but you know what I mean. It can go through each bite individually. On it is great because it avoids you happen to use things like loops, toehold indexes and so on. Right, So a lot SB instructions. Great for that. And if I just go back to the instruction set quickly. You can see that it also relies in the data segment, much like many of the memory operations. So the air sized offset from the data segment. So if you remember the physical addresses, the data segment multiplied by 16 plus s. I So that's the lot SB instruction. I I hope that makes sense to you. Ah, nice handy feature. That is how we were able to go through our entire message when we out putting our hello world with the print. 15. Storing bytes with the stosb instruction: So if we now take a look at that s t o S B instruction, this works like Lord SP, but instead of reads, it writes. Okay, so what happens is it stores a bite? It stores the biting the oil register into E S D. I. So, in this case, instead of the data segment, it uses the e segment the yes segment. Right? So then it will either increment or deck Ament, the D I register based on the DF flag. So let less now where? Let's no try that out and see what happens. Right. Okay. So I want you to do then in here. I want you to go move a l and we're just gonna do a capital A All right now, just below. Read by here. Do message db Hello. World like before, right? Andi, if you know this here instead of using s I register, we need to use the d I register. This points to where we're gonna be writing to. So if you just go move d I message and then do s t o S b. You know, press emulate, and we're gonna single step. So that puts 41 hacks into the low bite of the X Register, which is a capital a And then we single step again. The d I register where we're gonna be writing to is now updated to our message. And before we go any further, I wanted to Crestview memory and you can see hello world here, right? Okay, that's good. Now press single step again. You can see that it's now become at a l o World. It's chip h is changed to an A So that's what the S t. O S B instruction does, right? It does the opposite to the Lord SP instruction. This instruction writes to memory on. If we was to call Stosur again, it would write another a overriding e eso That is how it all works. And just to demonstrate that let's put another stus be here presently late again. Press single step single step pressing step again First bites garden Press it again. Second bites gone so you can see how it's working by increment in the d. I register every time it writes, one bite to memory allows us to easily right to the other bites just by calling the same instruction again 16. Revising Our Hello World Program: Okay, guys. So now that we have explained all of that stuff about the 8086 process er, you should know. Know enough to be able to understand our hello world program initially. So I'm gonna go through with you Based on what we've learned just to go over it on, I'm sure you'll also understand now. So our program first ends up being run Onda. We hit a jump instruction which shares to jump to Maine. Now we can see main down here, right? This is a label. The address of the labels resolved, assembled time. So this jump becomes jump on, you know, some address, right? That's why becomes once is assembled now. Because we jumped to Maine, we skip over this message without this main jump main here, the actual assembler will will assemble code that will that once run will try and run the hello world message as code. Right? So, by doing a jump main, we jump over all of this to our main so that it doesn't run any of this right, because we jump over it on Take a look at the understanding the process of video form or oven understanding on how this jump works now and our main function. We move the address of the message into the S, I register and then call print. Why do we put the message in the S? I register because remember, the Lord s B instruction uses the S. I register to know where to load a bite from. So what happens is we move the address of messages, the S I read. So we call print, which now jumps up here. But it is a routine, so it will always come back. We move zero e hey h into the A into the any age register. Zero e page is the function code for one we call interrupt. 10 page, right. So it knows which. Which piece of code to Rome. If you remember the interrupt vector table research about that to understand interrupts There's an interrupts lecture in this course. Now, when we go through here, we move Syria e hates into the age register. Then we do a lot SB so that will load Hey h into the a l register. Right. We now compare that with zero. Because if you look here, this zero here, this means that we're done. We put a no Terminator here on. Then when we're printing out, we check if it's there. If it's there, then we jump to done, which returns from up from our subroutine, which puts us back online 26 which then returns and shoulder M s DOS. Now, obviously, if a l is not zero, then we never jump to that lead to that done label. So the coat carries on running and calls interrupt. 10. Hey H now interrupt. NH sees that the function is zero. Hey h on it sees the A L Register is whatever character was selected here on it, and it shows it to the screen. Remember, all that we use is you hate for here is it's just represent a function inside this routine here that inside this interrupt here injured 10 page. So interrupt 10 page might have a bunch of compares saying, If this is you a page then jumped to our output to screen routine. That's all that's happening here, right? It's just in this case in Trip 10. Hate is our video routine. On this is the function that tells it to output one character to the screen that that sold you need to worry about on that is how our hello will works. So buy less press emulate So we can just step through it so you can see a little better. Okay, I'm gonna close the memory view just because it's easier to understand. Okay, I press single step That jumps to main. Yeah, we're now running main single step. We move 102 Hey h, which is thes the address of message. By the way, into the s. I register now. Where was I? Okay. Yeah, I seen the step again. Now we've called print and now I single step again Zero he hates goes into the a H register , which is the function for our video output. One character routine. Remember when we call into a 10 page Now we single stepped this Lord SP's We see 48 page in the ail register, which is which is basically a hate character here. Right, So we go back, Onda um we then single step which compares ale was zero while a always hate So those flags here I never set So jump zero George jumpy jump equal will never jump So we press single step that goes onto our interest. 10 hatred team single step again on that Outputs hates to the screen. Okay, Now, uh, what happens next? We have our jumped by here, which jumps back to the loop. So then we call lot sp again, which loads in the next character on. Remember, the s I register points toe where it is. If we go to view and memory and you just type one of three in here, you can see the first character here is e right. It's e So this is gonna be the next character this red. So if you press single step, then you can see this has now become 104 The a l register now has e If you now put 104 in this memory access, you can see the next characters l This is how it works. Guys. Lord SP takes then increments takes then increments Right now we single step again ale is not zero single step against in the step again. Single step again. Now we output e to the screen. This goes on and on and on until, uh, not SB reads are no Terminator here in which case? Uh, compare a L zero. We'll set the correct flags, which will cause Jay Z or jump equal to actually leave our program on jump to done. Okay, well done. 17. Helpful Resources For The 8086 Processor: Okay, We've always concluded the 8086 process, and now, and we will soon go to more modern processes because I think you've learned everything you need to know about the old ones to continue this. But before we wrap this up, I want to show you some helpful resource. Is so the first ones. Ralph Brown's interrupt list. This is a fantastic in Tripolis, compiled by somebody assumes called Ralph on. But it shows you all the interrupts for the bios on the function, the function you need to pass in the age registered to call it. It's fantastic features, so I recommend reading about this. If you want to stick with the 8086 processes for a bit, um, Ralph Brown's interrupt list. Just such than Google, you can go through categories, interrupts. It shows you everything that you need to know for how to do that. Such a zoo mouse input reading from the keyboard. Very, very useful resource, that is. But what you learn here will only be able tow work in real mode or on the 808 sex on. In case you didn't know riel mode, it's a compatibility mode that all modern processes starting before the operating system boots. So I just wanted to make that clear. So anything here will only really work on the 8086 Okay, again, we have Dawson dropsy a m s. Dustin drops. Um, the the M s DOS interrupt is 21 page on these air the functions that are available. So if the h is 01 then we read a character from standard input, uh, so that this is another good resource. So you can type m s dos interrupts and Google and you'll see something like this. It should work fine with this annual ator. Um, so these interrupts for the M S DOS operating system again. This alone, you really work on older processes such as the 8086 but it's definitely worth a read. All right, then. So next lecture. Now, then we'll stop writing modern assembly 18. Installing x86 Assembler Dependencies Revision: Hello and welcome everybody. So we've now completed the real mode development of this costs. So you've learned legacy Intel assembly. We're now going to install NASM, which is an assembler and also mingled. Okay, So if you go back to dragons app.com forward slash downloads, and just click X86 assembly language master's course. And you will see the X86 dependencies here. If you can find the downloads page, go to dragons app.com, scroll down and just press downloads at the bottom here. Okay, so I just scroll back up. We're going to stop by download NASM. So just click NASM to 2014 download. And we're just going to run that installer. And it'll say that the software is currently running as an I'm privileged user. So if you get that, just press cancel. Okay, and we're gonna press to open all files. And we're going to right-click on the NASM installer, run as administrator. And then just press yes. And there we go, that will run as administrator. And now just install for everyone on this computer. Just keep pressing next. You don't have to do anything else. Just make note of this path here. Just remember it. Press next and finally install. And now that'll install the NASM assembler. Okay, press Close here. And if we now go here and we type CMD and we go NASM will see it says it's not recognized as an internal or external command. This means we need to set up our path variable to recognize the NASM assembler. Okay, so to do that, we need to go to our File Explorer and just go to the C drive. Go to Program Files where we install did find NASM. And this is the directory you want. Copy this path here. Open up environment variables. So search for E, N, and M. Press edit the system environment variables. Now press environment variables. You'll see path here in your user variables, and then you'll see your name and you'll see path. Just click that and press Edit, press New, and just Control V and paste that in and press. Okay. Now you'll see the system variables go to the Path, click Path, press, Edit, press New Control V to paste that, press. Okay, Press Okay, I'm press OK. And now we need to reopen command prompt, so close it and reopen it, type NASM. And we can see that NASM is now getting resolved. So that's how you set up an ASM. And we're now going to do the same for Ming gu. Okay, So regarding the Ming GU compiler, this needs to be 32-bit version. So just use the one on the website and then you'll know you're getting the right one. So Ming GU compiler download, just click it. And it'll say Ming Gu W6 fall for 32 and 64 bit Windows. And this particular one we're installing is the 32-bit compiler. So you'll, you'll see in a moment. So just wait for this download to start. It can take phi seconds. And then you'll see Ming Gu 64 installed. Just press say fall. And now just open that up. And it'll say welcome to the Ming UW 64 installation suppress next. This version might not matter because GCC tends to have bite, which can be anyway. However, if you want to be on the safe side, just select the same version I have here, a 0.1. So just press Next. And this is the destination folder. Okay, press Next. There's some now install Mango compiler. It can take up to 15 minutes. So just pause the video and replay it when you have finished installing it. Now that you've finished installing Ming Gu, press Next, and it will say that you completed the installation. So again, if we go to Command problem, we type gcc, you'll see it's not recognized as an internal or external command. We need to change the environment variables again. Go back to your file browser, click this PC. We're gonna go to the C drive Program Files X86. Well, that's the one for me wherever you installed it, guys. Okay. Ming Gu dashed W6 fall, and then open this directory and you will find mingled 32. All right, When you're in mingled 32, double-click the bin directory. Now this is the 32-bit compiler we care about. Okay, so just go here and type ENV, edit the system environment variables, and just go to environment variables. And we'll see path here, okay, it'll say path, press Edit, press New Control V. Go to the one here. Press Edit, New Control V, press, Okay, press Okay. And now type gcc and it'll say it's not recognized because we need to reopen command prompt. So close command prompt, reopen command prompt type gcc, and we'll see fatal error, no input files. So we've now successfully installed NASM assembler amine GU compiler. So we now have everything we need to stop working with assembly in C. So thanks so much for watching guys and take care. 19. X86 Hello World: Hello, guys. And welcome. So you're now ready to create your first Windows programming assembly. Now, I've just created a new folder and created this hello world example file here just for our putting hello world to the user. I just want explain all this to you. You guys should definitely pause the video and copy this and do exactly as I've done here. Okay? Right. I'm gonna explain it now. Here we do. Global Maine, right? This means that were making this external to other people. So other programs will be able to see this symbol when we compile in link our program. So without this, they wouldn't without this outside. Outside sources wouldn't see our main label here. Right here. We say X turn, print F. So what we're saying is there's a print F label somewhere, a print of symbol somewhere we want to access it. We don't know where it is yet, so just pretend we know where it is, and we'll resolve it later at link time. That's what that means. Section dot Text. Everything under here is code, right? You have different sections. So you have a data section where data would go. You have text section where Cho goes and you have other sections as well. Now, down here you'll notice our message messages. A data by hello world A new line and annul Terminator. Now you'll notice this is in the code section. It should be in the data section, but I'm trying to keep this A simple is possible for you for now. So what happens is when we compiled and linked this you will get inexcusable file. Don't yet see one that's run. It will call a start symbol which we haven't defined by the way. And then that will call arming function here right under school main. So here what we do is we pushed the address of the message to the stack. This is our message here, right? We call the print F sub routine, which then outputs that message and then we add four to the stack pointer, basically taking our message off off the stack, essentially, so I can assume you have all that written up now and I'm gonna actually assemble this. So all I want you to do, I want you to open up command prompt in the folder where your program is and you know, you can use CD to get to that, by the way, CD paste in the address. And then I just want you to do Nazem Dash F 1 52 and then just you filed I sm press enter that will assemble it. And now all I wanted to do now is go GCC filed r o B j press enter that a link it that a link it with standard library and all that sort of stuff, right? And now if we now run a don't yet, see, you can see Hello. Walked. So congratulations your very first assembly program. So a little bit more back to the ad e s p for them san she because we push this to the stack. This is on the stack even after we've called print f. So by adding four to that, we we basically change whether stack point is pointing, so it no longer points to this message here. Okay. And that's pretty important. Um, the reason we use for here instead of two is because in win 32 systems, four bytes is the size of a word. And if you remember when you used that stack to push and pop your You're using words. I eat two bites in the eight oo 864 bites on this process. Okay, so So that's how that works. And if you look at the sea equivalent here and in case you didn't know already by using a semicolon, this is a comment. It isn't interpreted in any way from the by the assembler. It's just used for our for instructing the programmer. What's going on? That's why you can see that there's this nice little headed by here, right? So here, then, if I do Hello, world. It's basically the sea equivalent. But because we're not in C wing assembly, we actually have toe push the message to the sack ourselves. When you compile this, it'll result in similar assembly code that you see here the matter of fact, just to demonstrate that I'm gonna I'm gonna find a C to assembly compiler online. Uh, you can you can do this with GCC, but I rather use the online one, because they're very nicely styled is easy to read. So I'm just gonna go see to assembly online and you'll see compile explorer from God Bolt, you don't have to do this. I'm just trying to show you what's going on. So here, then I'm gonna go. This is See, by the way. Now, I just want to show you the output when you compile this. Right? So I'm gonna go see inch Jermaine, um, on in here, I'm going to go Prince F. Hello world. And I'm also going to include STD I o Okay. So you can see they've compiled this a little differently. They call putts, But nevertheless, it is the same type of thing, right? They've optimized it a little bit. It's gone through a bit of an optimization, I think. But you can see that when you can Policy, it just becomes assembly. Right? You can see here string that has hello world. That's just like our DB data bite right on. You can see that it's generate a bunch of this assembly on, you know, that's all how it works. We compile something and then it gets out. Put it here 20. Using Assembly With C : OK, guys. Now I'm gonna show you how you can make see with assembly. Now, I know this is an assembly costs, but because a lot of the routines were calling R and C is pretty important that we get this right. So it doesn't matter if, you know, see, or if you don't just follow along because you need to understand how all this works and you're about to get very confused, which is completely normal. Uh, I'll just help you get through it. So the first thing we're gonna do is we're gonna create a C file. I want to create new file here. Call it main dot C. I'm going to go into Gia Oxy. No instrument site in shock. C sharp RV. We're just going to 10 0 here, okay? All I wanted to do now, up here, I want you to go x turn. I anti my under scroll, sm, and that is all I wanted to do for now. And makes you have a semi colon there, guys so should look like that. Extend. I anti my some right. Okay. Once you've done that at the very top here, include the STD I ohh! header so we can output some information. All the ones you then do is go into a job offer Result equals my underscore, Lius. Um And now I want you to go print f value percent. I backslash end for it for a new line character on We're gonna passing are here. So if you try to compile this, nothing's gonna happen. It's gonna fail because we haven't defined this anyway. We're gonna define this in, are actually actual assembly code and then link our link our object from our assembly code with the object from our C program. So essentially, we are mixing, see and assembly. So go defiled our sm on we're gonna change a few things. First things first, get rid of all of this no longer needed. Next Globe Garrett of extend here as well. So we should just have global and text change. Global Main two under scroll My underscore A sm. Now this is our function name. If you go back to maine dot c, you can see it tries to call my and school a ASEM. Now, when you compile the see program, all the exported symbols of functions start with an under scroll. So when we do this, it's actually looking for this, right? And if we go back to file delays and we can see, we've said Global under scroll my under school A SM. So that means that if we then define a label here, and I want you to do this, two guys underscore my under school A SM. Then it resolves that link. Right? So when we won, we won. We assemble, filed a sm to an object file on we compile, may not see into an object fell when we then link those two objects, they resolve their dependencies because, see looks for this with an under scroll of the beginning, and it finds it with us because we announced that its global here. Okay, so I just wanted to put r e t r e t by here for for refer turn. Because if you remember, they're calling us right. We go back to Maine. God, see, we call the Maya a sm function, which is us. So that is just subroutine, right? Like the one the sea is assembled to assembly and then to machine code. It uses the cold instruction in the processes instruction set so and nose to call us because it uses the call. Instruction in the processes instruction set were expected. Toe Call the return instruction R E T. Inside of that instruction set to return from the 17 passing control back to the sea program. So let's now assemble this and compile it on Link the two together. When you run this program after we've done this, it will crash, most likely, but that's to be expected. So all I wanted to do then I wanted to go. Uhm, I'm going to do Nazem f 1 32 filed A SM greats. You've done that. We now have a filed O b J Foul on now do GCC main dot c Filed a O b J Dachau Main Press Center and you can see we now have a main program. If you now put type, main and presente, you can see the values one so it didn't crash for us. That's fine. Now out. I'll explain why it's one in a moment. Now let me just explain this by using Nazem F 132 We we assemble our filed on a SM file into a filed R O. B J Now, this is an object Father contains loads of symbols contains all our all our assembled code on rules on how to use this file. Right now when we do GCC and we pass in maine dot c that compose our main dot C program R C application right R C program. But it also links the result with our father O B J Fall resolve in that my A s N dependency here and then the at the outcome is excludable file where that that knows where all those symbols are Because we've linked ID with our object foul filed a o b. J. So that is how our main program can call our assembly function. Because by assembling this filed, I sm on using the global keyword here we export are my same label so that the main dot C can resolve it during link time. Okay, I hope that makes sense. This isn't really a link, of course. So I suggest reading about that if you're still confused. But anyway, that's how it works. Now. Our function doesn't really do anything. It just returns pretty crap right now. You wanted to know why the value here is one. The value here is one is because the e X register contains one. Now, we haven't really covered the X register in in more modern processes. You haven't e a X register, which is basically an extended a X register. So remember, we've been work with ex while in it in modern processes, we use E x on a lot of the registers A like this on that they're much larger registers. Basically, uh, so let's now return 10. I don't like I don't like the fact if it turns one. So to do that just above your right instruction do m o v e x 10 It's a simple is that Now I'll explain this in a bed, go back and press the fro in command. Prompt. It'll go go to the old commands run then as in command again, and then run the compile command again. GCC main dot c filed a o b j. Dachau main Dachau means the output name, by the way, which is why we get main Dottie XY type main enter. We see value 10. So why is that? While the sea, the C programming language expects functions to return values in the E X register now 11 The compiler compiles your C code to assembly it. Make sure to follow this rule. So the rule here is to talk with C programs from assembly. You have to know that C program always expects the return result from a function to be in the X Register unless is too large and then it does other things. But for returning things like intra jizz stuff like that, you should be returning the result in the e X register. Right, So here we go. Move E x 10. So we move 10 into the X register. So then our main dot C program. When it comes back around, it knows to store the X register into the r variable. Great. So now that's being explained. I'm gonna compile a mean dot C file again, but this time I'm gonna output the assembly on, and that will allow me to go through it so you can see how it's all working. And you should definitely do this as well, by the way, because it will show you exactly what you're doing wrong. If you make mistakes, right, so just best the up arrow So it comes back to this. Andi, just put, um, just put Dash s at the end here and change this main to main dot sm. So the dat Dasha s flag means that we were not interested in creating an excusable. We just want to see the assembly. So if you press enter, it will give you a warning here because there's nothing to link because we just output in the assembly code. That's normal. But now you'll see a main dot sm filed by here. If you go into here, it's gonna be really confusing, right? It is quite confusing. So you may want to re compel that with optimization off. In which case to do that you just passing the flag 00 and then just do that again. And now it will re compile it, but it won't use the optimizer. It might be a bit easier to read. Okay, so now we can explain this, and it is pretty confusing. Okay, so let me remove what we don't really need to worry too much about just yet. There is some serious stuff that I will Well, I will show you. I try one. Remove it I'll just make some space so you can see what we care about here. Okay? So you could ignore all this for now. Here we call our function, right, my ASEM and then the line underneath that you can see this instruction. Now, before we go any further, I need to explain something. The output from the GCC compiler is the opposite to the way we've been doing it. In this case, the destination argument is in the second operation, not the first this this month. This this 28 here represents in memory where our are there are variable is okay on. Remember what I said in previous tutorials Back when we did the ADA wait six stuff. I said that local variables in C are on the stack. Well, this is what I meant. So back to main dot sm we store the result off my somewhat. It returns into the R variable, which is represented as 28 on the stack by here. Right? That's what is represented. Ads. So now that we've covered that, I hope that makes a lot more sense. So, in our file Delius em, we set the a d a X registered to 10 which is our return result back in maine dot sm we move that value from the X register to somewhere on the stack here, which represents our bearable. Okay, so whenever somebody wants to communicate without are variable, they will do it like that. You can see they do the same by here, right? Because now, when moving, um, now we're moving it into the e x register. Right? I would say the optimizing may took that out before, but that's all you need to know about that disassembly right now. I just needed to demonstrate that that's how it's working. So it gets compiled into into assembly where they call us, right? And then they moved the result here online 24 into the r variable. That's all you need to know about that right now. OK, now that you know that we can get more complicated about this, I want you to change your ex, turn into Jeremiah, Sam, we're gonna pass in some arguments, So we're just gonna go into a and B and we're gonna make it, so it sums them together, right? We'll keep it cold is my ass. Um you can change the my some if you want, but this is just more clear, right? So make sure the numbers are different because you're gonna need to be able to tell the difference, right? So I'm just gonna put five and 10 in here, so this will send those together and store the result in the r variable. So we go back to file today s m. We need to change this drastically, and we need to stick with the prototype was supposed to. So the first thing I wanted to do is push the base pointer to the stack. Okay. Now, pop the base point of from the stack here. Now, this is important. This is This is how the C compiler a set compiles into assembly. You need to do this because things like Rick Ocean and stuff may require it on calling other functions as well. You should. You should definitely do it like this. Okay, so now here you go. Emma v b P s p um so Oh, and I also have done based pointer here. Right? This should be e based pointer, by the way. So change all of those to push e b p move the stack pointed into the BP register, so that should be E B P and E S P poppy be e B p. Sorry. So make sure it's make sure it all has he at the beginning. Like I said, in these modern processes, you know you have e BP registered E X and so on, right? If you don't do that, you may run into problems. Best to do it properly, right? Okay. So way have it'll set up correctly now. So we haven't discussed the BP register yet, have we? Right? The base pointer register is basically can be used with stack point of register as kind of a way that toe access the stack without modifying or making changes to the stack pointer on its also is based just on extra register for sort for storing the stack point of value at a given time. So by doing this, we can access the stack through the base point of rather than stack pointer because that they basically contain the same value. That's all you need to know about that. And obviously we push the base point of here just to save the old value for later, because if we make any changes to the space point of whatever, we we don't want the returning function to have those changes, right? Because it might cause program to crash or bad things to happen. So by pushing it here, we save it for later. And then we pop it off. Aziz. Well, by here, which basically returns it back to what it waas before we pushed it here. Right. I suggest reading up on stack frames because our stack fring composers of the whole function here, right? So so including the return address. Because you have to remember, right, that by pushing this on by the program, calling us it's changed has changed the stack. So we need to take that into account when, when working with our assembly here. Okay, so I'm now going to make it. So we returned one value rather than adding them both together, right? We can do that later. So what are you going to make a new line and into your do m o v a X? And this is gonna be confusing by the way. I'll explain in Oldham Worry. Just do this. And then e b p plus aids on I just want you to assemble that and compile it. So first assemble filed a sm into Faldo BJ using that command on. Then you want to use GCC command here to link the two objects to create the main file Enter type Main on. We see value five. And now I want you to change this to 12 on do the same. So we reassemble, re compiled May, and now we see 10. So we now know that five is that e p P plus eight on 10. Is that UBP plus 12? Well, how does that work you're asking? Well, how is that even working, right? That's what you're thinking. Don't worry. I'm going to show you right now, So I want Asturias. I want us to re compile R C program again, But this time we're gonna put the s flag again, right? So change this output file to means of sm on for the dash s at the end There we now go to Maine. Dar es en on. By the way, guys, if you already have made our air some open need to close it before one in that command. Otherwise you won't see the changes. So if we come in here now that I'm going to separate what matters here we move immediate. 10 into the stack. Point of plus four. Here we move immediate five into where the stack pointer is currently. Okay, Now, remember the GCC output of assembly? It works differently than the assembly. We right? Because here we move from source to destination. So the sources on the left and the destinations with right, Where is the way we do it? Destinations on the left and the sources on the right. OK, so here we move 10 into the stack, point of plus four. Here we move five into the stack. Pointer. Um, plus sea route plus nothing. Okay, so our values stored on this stack. Okay, we go back to our federalism. I'll explain how we are accessing those. So, um, here we push our base pointed to the stack, right? So just demonstrate that. And as you plus four Ok, that's important, By the way. Now, they also called us using the coal instruction, which also which also pushes to the stack. So we'll do another plus for okay, which is eight. Yeah. Nice is important to know so words in modern processes are four bites. Not too. So a call instruction uses four bytes. Not too. So pushes the return address, which is four bites. Right. Uh, you any any action with stack is four bites. Right? So here we push our base pointer to remember for later. Right on both of those together. Make eight. Okay. And now I want you to do 12 minus eight. So 12 minus eight on. I have to use a calculator for this. I can't do. My head is full right now. 12 miners say it's for So if we go back to our means, are they ASEM? What do we see here? We store 10 in the stack. Point of plus four on That gives us 10. Yeah. Said you see how that's working, right? I know you're shaking your head right now, so I'll go back. I go back to tell you again, right? When we go in here and we call my sm, we are calling. We're using the call instruction which pushes the return address to the stack, which takes up four bytes. Ok, when we push our base pointer that uses another four bites, eight bites. Right. So now we move the stack pointer, which is eight bytes ahead of what it waas when they called us here. Right? Because when they call us here that moves the sack pointed by four bites. Right? When we push here, that moves the stack point of by four bites. So where eight bytes out, Which is why we plus 12 to get 10 on, not plus four. If we plussed four, it wouldn't give. It would give us the wrong value because where eight bytes out. Right? So by plus in 12 it takes into account that we've pushed the base point of here, and it takes into account our coal instructions return address that was pushed to the stack when we what? When this instruction was run. So that's how we can offset to the correct one. Okay, so I think that makes more sense now, right? If you're still shaking your head, drop me a message, I'll try and explain it a better way. This stuff is quite complicated to explain. Um, I've had years of exposure with this stuff on. I know how hard it is when you first begin. Right? So I've explained that. Now, if you still don't get it, you you'll probably start picking up as we go along. I know I was going to do this. Some in this video where? Something both together. But I have to explain local variables, which is a lecture in itself. So we won't explain that in this video we'll explain in the next one about local variables and how we can use them. Now. You've successfully returned the value that they have passed to us, so congratulations. 21. Local Variables In Assembly: hello and welcome. And in this lecture, we're going to discuss local variables in assembly language. And finally, how to some two numbers together in assembly. Let's begin. Okay, So the first thing you need to do is go back to your assembly foul, filed a sm, and you'll see this code from last lecture where we returned one of the arguments provided to us as the return results. Well, that's just to lead that line. So you assembly should now look like this on I'm now gonna first show you how to do local variables. So the first thing you do when you just attract stack pointer by four, so do sub e s p for and then just under their do add e S p for so variables in assembly don't actually exist, right? What we have to do, we have to make use of the stack to do local variables and see also does this thing, it just gives it to you in a nice way. We can create introduced chars when it compiles it into assembly. It does what we're doing here, uses stack, right, uses the stack to store local variables, so you can think of everything between this sub On addition as a scope, I think here that we create a scope in C right? If we did this insta equals 30 Insta is only accessible from within this scope that I've selected here. If we try to access it here, it does not work, right. Well, not only is only accessible here, it actually only exists in here. After we leave this scope, that stack pointer is returned back to its original state before entered the scope, which means that the memory in a is no longer accessible Back to follow a sm. Let's now set a variable. So follow what I'm doing. Move D would e v P minus four. 30. Okay, so what we do here is we are now using the room that we've made and assigning that room to value 30 on. We're moving a double word as specified here. And a D word or double word is four bites. So we're saying move four bites into the base point of minus four. Move the value 30 into that location. So what we've done here can be seen as our instrument. A example in stra equals 30 right? So inches of four bites. So we've subtracted four bites from the stack pointer to make enough memory to store that data. Right? Onda. We set that data. It's a 30. So although 30 can fit into even a chart because the data type is an interest, your we subtract four bites. I should also note the one making changes to the stack like this. You should be sure to keep alignment. For example, if I subtracted three from the sack point of this is bad practice, it should be aligned correctly. For example, 48 12 16 are all fine. 32 64 128256 are all fine. Keep the alignment. Don't do things like subtract in the stack pointer by one memory works better aligned. So I imagine you're still a little confused, so less explain how this is working. To do that. We need to start here. Here we move the stack pointer into the base pointer. Okay, now, just for argument's sake, let's pretend that stack pointer is equal to 1000 right? So after this instruction is run, the stack point is equal to 1000 still on the base pointer is now equal to 1000. Also. Now, next, remember that this stack grows downwards in intel processes. So here we subtract the stack pointer by four. So the stack pointer now becomes 996. However, bear in mind that the base pointer is still 1000. Okay, so after this subtraction, the stack point is now 996. So what does this mean? Well, because the sack grows downwards. We have now given ourselves for bites of room to store some information. So what do we do? We set EVP the base pointer minus for equal to 30. So what does that do? Well, 1000 minus four. It's 996. So this becomes move 30 into address 996. Because we're moving a d were, which is four bites. The full four bites are over written, so it will overwrite between 996 and 1000. It will overwrite those bites with decimal 30. And, um obviously, because 30 does not fit perfectly into four bites, the remainder of the bites will be zeros. So then what we do is we add for to the stack pointer, bring in the stack pointer back to 1000. Okay, so if you remember, we plus on the base pointer to access arguments passed to us through function calls, for example, on we minus on the base pointer to access our own local variables. So let's say that you wanted to local variables in your scope. How would you do that? So trapped stack pointed by eight at the SEC, pointed by eight. If you now do move D would e v P minus eight equals 80. You will see that you now have to local variables again because assembly doesn't actually have variables. We're just working with memory here. So just to demonstrate how this might work, I'm gonna label them in a C type fashion. So it's almost a Ziff we've created, available, named a, said it to 30 and we've created variable named B and said it 80. Okay, well done. So why do we add to the stack pointer? Because we need to restore it back to what it waas. If we don't do this one then caused our pop instruction here, it will pop off the wrong base pointer when it then calls are Rhett instruction here, it will pop off an invalid return address. So the stack always needs to be returned correctly. If you subtract from the stack pointer, be sure to add back to the stack pointer. So just to demonstrate this, then let's now add our two local rebels together. So how did you do that? Just go. Move B A X de would e b p minus fall. So this will store our value of 30. Here are variable. They will call it variable A as represented here. It'll start out. It will store our variable A in the X register. Okay. And then all you have to do then is go ad e x with D would e b p minus eight which references our second variable very will be here. And if you now assemble that using makes you press control, that's to save. If you know, assemble that using Nazem Dash F 1 32 Father S m and you press enter and you now compile it . Using GCC main dot c filed a o b J. Dachau, Maine and you now run main. You'll see 100 and 10 if we now do 30 plus 80 on Windows calculator, You can see the results of 110. So our program we've done here essentially looks like this in Shake was 30 in ship E equals 80 return A plus B. Everything we've done here, life highlighted is basically the sea equivalent that I've commented down there. Did you see how that works? We move variable a into the X register. We adds the X register with variable B. And obviously, as you know, the add instruction sets the result into the E X register. And obviously, as you know, the add instruction sets the result to the first operation provided which in this case is E X. So it adds E X with the base point of minus eight and stores the result in the X register. Okay, on E X register is used for returning values. OK, so we're not quite done because we're not summing the data provided to us. We're only summing the's literal numbers we have here, so let's change this a little bit. Now let's set our local variable toe one of the arguments provided to us and in their set, the next local variable to the other argument provided to us. Now, Before we can do that, I want to show you a common mistake people make. So you don't make the same one. De would be BP plus eight. Now, what is wrong with this? If you try to assemble this, this one work. Because if you look at the instruction set the X 86 processor, you can't do assignments like this. You have to have one of them as a register. Okay, We need to instead. Go move yaks de would e b p plus eight. And in this here becomes E X. Okay, And then that work, and then down here, you need to go move E x d would EVP plus 12. And this becomes B a X. Now that is valid. That'll work. So you see, if you check back at our last tutorial you remember that by doing EVP plus eight, we can get one of the agents provided to us and BBB plus 12. The other argument, right? The the arguments being the five and 10 provided to us here. Okay, so ah, check back of that lecture if if you're confused about this, um because I go through it and I explain every individual point of of the reason we use thes offsets. Okay, great. So if we now assemble that again by doing Nazem f 1 32 falls on the A S m and then we do GCC may not see Faldo. BJ Dachau Ming When you were in Maine, you'll see the value is 15 which is a successful some five and 10. So I'm just going to go through here and give it to these comments and just write some more comments for you. So you know what is going on? A little better. So remember, we're going to just call this variable A, you know, just keep it simple. So what we say here is, we say, um insta a equals inputs. Um, thesis pseudo code right now, by the way, Input zero. So the first so that one of the Aryans provided to us. Okay, here we say. And should be equals input one. Okay, so once again, this is pseudo code. Okay, Um, I just try to make it bit more readable for you. So these two lines here said our imaginary intra a. So one of the first arguments on in stripy equals import one here. Um, the pursuit of code I wrote that represents the next argument being set. Okay. And then here we basically say return a plus B. So that's the pseudo code to represent this. Okay. And then all of us see, this attraction of the stack here could be seen as a left curly brace on the adding of the stack here could be seen as a right curly brace to represent our scope. So I hope that makes sense. I've tried to break that down quite a bit, but that is how to do local variables in assembly. And also how to some two numbers together. Eso I hope that you found this lecture useful. Any questions, please ask. 22. Returning Structures In Assembly: Okay, so we're about to do something pretty complicated. We're going to return a structure from assembly, and it's not the easiest thing to do. To be honest, it can get a bit confusing. So follow my lead in the sea program. We're going to create structure called test. Okay. And this is gonna contain one introgen named a Someone shining Be okay. Now our assembly function here. We need to change this to return. Instructive test on To keep things simple. It's gonna take no arguments. Okay, Now here. I want us to do struck test A equals my ASEM on. We're just gonna tow output the character here on the chart here. Right, So we just go eight or a a Don't be okay. Right now that we've done that, if you just compile that a minute, it'll crash the program. I just want to make sure the samples Fine. Yes, it does. Good. If you run main, it doesn't crash. But you know, it is unexpected behavior. Let's go to Faldo A sm on. We're now going to set the values in that structure. We are returning. Okay, So follow my lead, and this will all be explained in time, Get rid of all of this because we don't need anymore. I wanted to go. Move E a x zero x f f f f f f f f So so Atef's guys. 12341234 Ok, now do move E d x which the DX register Just putting capital A in there. It s a little be explained, but I want us to assemble. Run that. So run the Nazem command, Run the GCC. It's like May on we C minus one a. Now rather than this. Actually what we'll do is we'll just put a number here instead of that because I've just overflowed it slightly. So just put a random number in their reassemble the assembly program re compile. So it links type main and we see our number and our character printed out. So we go back to maine dot c We can see here we output are in Georgia here we out put out be introgen. So how does that work then? Well, see will use the registers where it can. Andi, this is how we're returning it now to explain this more, I'm gonna disassemble our main program. Andi, Then show you how it is calling us and what he expects us to return. So to disassemble the main program again, run the GCC command, but put main dot A sm here on just attach a dash s here. Capital s on. We want 10 optimization off, so dash 00 press until you get this warning. That's fine. Click mainly, I sm, now in here. You can see Let me separate this for you. Here. You can see it calls our function, and then it puts the e X register into its ah into into a stack stack location on its stack , and it puts the E d X register into into a location on stack. So that corresponds to us doing a dot a a dot Be right. So by looking at this disassembly, you can clearly see that it expects the first argument to be returned in the X Register on the second argument to be returned in the E. D. X register. And this is because, um, a is an intra job taking up the entire E x register and, um, our second car, our second is a chart. So then we use the E d. X ridge to here, which is also the same size. Is that the X Register? But this is just how it works. Uses, registers. Where can So that's how we return a structure. And I know it seems quite messy and difficult, but, you know, this is assembly guys. That's how it works into the hood. Okay, so what if we add 1/3 shar? How do we then set that? Well, that's first to this. Shall I put three characters now? Goto filed a sm and now just put a P by here, you see, it's really it is just like that. Go up here, recon part, reassemble the program, then we compile it outside May. Now you see a big So if there was three chars, you just had a c here and want it can't use that register anymore because there's just not enough room. It just moves to the next register that that's how it does it. So what happens if I was structures too big and there's just not enough room to store everything we need in the register? Well, I know what happens, but I'm going to show you by disassembling our program. First things first. Get rid of all your primitive variables in here and we're gonna make a buffer. That's, uh let's say 30 bites wide so that it won't fit in the registers properly. You're gonna have to get rid of this thing. Here is Well, we're just gonna change it. 2% s r percent c. Sorry. And we're gonna pass in a dot buff zero. So just outputs one character, the first index of the of the buffer in the structure. So the next thing you want to do is you want to compile this program, but we want to output it as assembly so we can see what's going on. So you do GCC main dot c Dachau main die sm dash s dash 00 to turn optimization off. And now we're gonna have one more command. One more command here now, which will display their disassembly in a similar sank text to what we're used to. We should have done this to begin with, to be honest, but I wanted to expose you to the different types of assembly there is on the different types that are formatting it. So you have to do is do Dash, Madam equals Intel. Press enter. That's now compelled it. We now go to Maine. Dar es en. We can see what's going on here. Back to our main dot C file Onda. You'll see struck tests here. Right? So the compiling knows we're returning a struck test because I've marked it. His ex turn here Right on. I provided a prototype. So I know somewhere, somewhere in an object somewhere on later on, it's going to try to resolve this symbol, right? It knows. So now that you know that, that's good. So back to maine dot sm here just before it calls our function it you'll notice the dust Something special. It loads Theodore S of E S P plus 18 This the stack point of plus 18 into the E X register right on. Then it moves that to the stack pointer and then it calls our function. So what is essentially done here Online 16. It subtracts the stack pointer mawr more than it would without more than it would if we if we didn't have to call that function on. The reason it does that is to make some room for us to fill in that structure that is being returned from this function. Call right from us calling this routine. So what we can do back in our code, we can actually access the address that's written here and then writes to that buffer. So once again, the address of where of up the address of the struck test gets stored on the stack just before they call us. Ready for us to filling later. So I hope that makes sense from this disassembly, right? I'm now going to show you how we can access that in assembly ourselves. So if we just go to filed a sm on you know, your sorrow code here, we don't need this now, so just get rid of it. I was just going to go m o v Um e a x ah e s p plus eight. That's all you're gonna dio, right? And then you're going to go a movie. Yeah, X, um, we'll go a like that, right? Just put bites by here, So we're only writing one bite, so let's just let's just assembling. Compile this and then I'll explain it. So back to command. Prompt. You're gonna want to go a Nazem half win 32 file delay. Awesome! And now that's done on now just do GCC main dot c Father O B J Dachau main Now it's like made on you see a So if we go back to our program, you can see we have put the first bite in the buffer. That is what's happening right now. Okay, back to our father s m. Let me explain this to you them. So I'm gonna go to Maine, lace em on, and here you can see it stores Theodore, dress on the stack at the current stack Point of position on the address stores is is the is the buffer we should write to. OK, one returning test now, once it stores that way we can access that later. Right? So then it calls us, right? So the stack point, the changes by four bytes. OK, don't forget, we go to files L A s m, we push our base pointer, file changes by four bites. Now it's eight bites. Now we move GSP plus eight because were taken into account that offset difference into the e x register. So now the address of test is in the X register right now. By using these brackets again, we access the address. Right. So what we do is we move a into the first index off that buffer. If you did, e x plus one on, we assemble that we can, Paula. And now you do main. You'll see random character here because now we've assigned Index one, not index zero. If you go back to maine dot C and changes toe one, we're gonna re compile that you can see a again. So hopefully that makes sense when it's too big to fit in a register, then it passes us and address that we can write to, uh, depending on our return type. Right? So we'll write the bites into where asks us to, and then and then it accesses them on its own stack when it returns. Such as here, for example. Okay, hope that makes sense. So before we finish up here, I just wanted to clarify a few points. Ah, you would have noticed I used the stack pointer here and not the base point of you should be using the base pointer, so e b p plus eight. And the reason I have used the stack pointer throughout this video is because the disassembly shows the stack pointer and I really didn't want to confuse you guys. So now that you've actually achieved the result, I can safely tell you this without confusing you. So ah e B P plus eight is the same as GSP plus eight. Because they share the same value. You should be using a BP plus eight because the stack pointer can change while the base pointer will remain the same. So ah e E v P plus eight will give you the same expected result. I should also note that the next few lectures we will also be using this stack pointer. I needed to let you know of what I was doing here so that you are aware of this for future lectures. So just to clarify again, the stack pointer e S P will be used throughout the next few lectures on The reason for this is because when we disassemble our main program, when we compile main dot c into a assembly file, we see that the stack pointer is being used to pass values to us. So the reason will be doing it like this as well is so that you don't get mixed up between the base pointer and the stack pointer. Just bear in mind that if you do decide to take thes exercises further, any changes to the stack point you make, you will need to make adjustments to your offset or use the base point up and avoid this problem entirely. The reason I show you with Stack Pointer is just to keep things simple for you. 23. Pointers In Assembly: okay, in this lecture we're going to discuss POINT is, an assembly are just going to get rid of some of this stuff on bond. Do void. Here, guys. So returns nothing on. We're just gonna take in a interest. Your pointer here. Andi, we're going to give it to this and were literally just going to go inches job. Um, a Onda We're gonna set that to 50 and here we're gonna go into your PTR equals absent a to get the address of a and we're just going to call my Assam PCR. And as a matter of fact, we will return some and give over 10 inches on. We're just going to go print F Sendai back session. We're gonna pass that. In the case of the idea, here is an assembly. We will read the value from the point of provided to us and just return it. So if all goes well, we'll see 50 here. I've just assembled this now in the background just to show you guys what it does. And if I just give it to this, you can see it works similar to the structures, right? It gets the address and puts it on the stack for us. So then we can access it later. So if we go to our file dot sm, we can actually try to access it now. So this here M o V E X, yes, p plus eight gives us the address off the point, OK, and then we can just do a movie. I say the address, I mean the value of the point of sorry guides. And then we can just do m o v e x, yea x. And now if we assemble that using Nazem and then we compile that using GCC main dot C Dachau main on dhere Also put Father O B J we now type main. We see 50 so that that's how you can access The point is you see what I mean. It works very similar toe the structure access when the structure gets too big, you know we are in assembly, so we're quite limited to the instructions we can use. So a lot of this stuff looks the same. So let's go back then I'll explain it one small. So we move the pointer address into the X register. So now the EA expressed a has the pointer address and then here by doing the brackets around the a X here, we say get the value at whatever the get the value at whatever the value E X is in memory. So, for example, if if he exes, let's just say 1024 uses a simple example. By putting the brackets around the X one, E X is equal to 1 1024 It'll that the process will go into address 1024 it'll pull the value out of where whatever the value is on that address will pull it out and then store it in itself in the X Register. Right? And remember, the X Register is the default way to return values back to the function caller so long as the result conf it in the registers. Right? So after this instruction runs E X, it contains 50. Because of this reason, because of what we've done here on, because in maine dot C, the inches A is equal to 50 by using e x, we return. The result took to the function that called us 24. Passing Structures To Assembly: Okay, guys, when I'm going to discuss how to pass structures to our assembly function and return into jail, right. So I want to do the two. Just so there's a bit more to go on here, Onda. It will help us make sure that you're aware of how to handle this when we return into you and we pass a structure. Okay, so in here, just to struck test t OK on up here just to struck test into a I'll tell you are no 90. A less to a big buffer again. Okay on. Um yeah, just for semi colon there. And yeah, that should work. OK, I think so. By here. Then do struck test t and we're just gonna pass him t there. Okay. All right. So what we're now gonna do is we're gonna assemble this, so I got a command prompt. Okay, so now you're in command. Prompt. Just do GCC main dot c Uh, Faldo BJ. Dachau main on. Then press enter and you can see when we run our program, it crashes. That's fine, because my asem doesn't handle this yet. Okay, So we're now going to go into assembly file on bond make the necessary changes to talk with our structure. But just before we do that less actually set some stuff here in the test structure. So let's just set index zero to a on index one to be. And then what General will do in Dexter as well? Said it to see, just so we have a bit toe work on right? And if we now compare that that compulsive fine and we're now going to go into assembly file and make this work properly, So all you have to do to see this working is simply Just remove this on Once you've done that, I know when you to go back to maine dot c Here. Right on. We're just going to cast this to Char here, right and change this 2%. See, just outputs a character rather than Instru, right? I want you to go to your program here. Do Nazem Andi dio the GCC compiler to compel may not see and link it is well type main and you see a So I'm gonna explain this to, you know, because I imagine it's a little bit confusing. Maybe for starters, we plus eight because of the return address and our push of the base pointer at the top here. Right. So we plus eight offsets to the correct position. That's the first thing you need to know. So I've taken the liberty of disassembling our code earlier on just so I can explain how this is all working, right? So I'm gonna make some room here. And this is our C program, right? And how it calls us. So way Push 65. Which is character A, By the way, to the standpoint of plus 46 character, be to the stack point of plus 47 cac to see to the stack point of plus 48. Right now, pay attention to this because this is important. Here we move four bites into the X register, right? And where where did the four bites start? At GSP plus 46. So essentially what it's doing is copying 65 66 67 into the X register. Okay, that's what you need to realize on there's if there's 1/4 by plus 49 that it's also copying , but we don't use that. Okay, now look at this. We move the X register into where the stack pointer currently is. Right. So that's what we've done. Why the compiler generate this? I don't know. Maybe because optimization might be off, But it does feel like a few wasted instructions, if you ask me. But this is what's happening. So, um, it copies e x register into where where the stack point is pointing to. Yeah, And then it does the same down here for the rest of the arrange for the arrest of the array in the structure. Right? Um, it plus fours each time because because it knows that the E X Register holds four bites, so it will attempt to copy for bites into E X and then add to the stack. That's why you see, plus 50 plus four plus 54 plus eight plus 58 plus 12 notes is a pattern. That's why it's copying your your is copying the data. So the stack ready for our function call down here, right? And I guess it makes sense that they're doing it like that because because we're not passing a pointer here, right? Were actually passing the structure itself to copy it now. That is why we can just do plus eight because they use the SP to store the 1st 4 bytes of the Ray Ray on Stack. We can't do that because they have cold us, which takes four bytes offsetting us four bites away from them. We then push the base pointer here off centers four bites again. So by plus eight by using plus eight, it puts us where we should be. Right. So this here when we do plus plus eight. Ah, the X register becomes a B C and some random character here because we've oniy assigned three characters, right? So you know, we'll just call this at or whatever, right? That is what's happening because the X rays toeholds four bites. Right? Okay, so let's say you want to see be were you just do plus nine, right? We If we reassemble that now we compile that tight main we CB on. This works because my ASEM returns and interest Your then we cast is a char, right? That's how that works. So you know, if you do 10 we'll see. See? Let's try that again. Now we see See you do 11 and we see that random data will see random data. Yeah, exactly. That was expected because no initialized. Right? We only said three bites here. Not not the third bite. The rest of the arrays, un initialized. So that's how you do it, guys. You know, you can see that. You know, you use assembly to offset from the stack pointer to access local variables, that that's how it's done. 25. Receive Input From The Keyboard: Okay, guys, let me show you how you can read. Read a character from a keyboard, them in assembly. Right? So, firstly, less get rid of this because we don't need this anymore. And we're just gonna turn this church are by here. Okay. Extension on. All I wanted to do is I wanted to go. HRC equals Maya Cem Prince f sent. See? Back session. I will just go see. Like that. Okay. Nice and simple. Now, if you go to file delay sm and here we're now going to call. I would get sharp function, which is in C. So the first thing you need to do is do X turn, get sharp. Okay? And now I'm gonna look the reference for the get sharp so I can show you How did you listen ? Assembly. Okay, so, looking at this, you can see the get shar the sea function, get sharp, takes no arguments and every turns and introgen. Okay, so the inched year returns is our actual char right? Our character. Okay, so let's go back to our code on then. All you need to do is go, Cole, get shot. It's simple as that. And we know that e x will contain our return results. So that showed that they entered Yeah, eso We don't have to do this to pass it back to the user a toll, right? Because he a x will contain the return results. So let's just quickly test this, then inside here. Now I want you to do Nazem F 1 32 main dot sm Oh, no mean delays and fouled. Ras. I'm sorry, guys. Yeah, on that is done. Now do GCC main dot c filed auto BJ Dachau main outside main. And you can see it's waiting type of key on. Then it allowed for that key to you. So, you know, can you see how we can talk with C library? You know, in assembly, You know, we know it takes no arguments, so we don't have to pass any, and we can just call that assembly function on it will return the result in the a X ridge to forests. Just to demonstrate this If you want to go Addie a X one Right on. Now check this out. Reassemble that re Kampala type main type A and U C B type C and you see D Because we plus one. And if you look at the asking table and look it up, I'm sure you know something about that already. The three characters like air in alphabetical order. Right. So by doing plus one, it gives us the next character in alphabetical order. Okay, so, you know, you have asked how you can get. That's how you can call the keyboard, right? I mean, we can do other things too, You know, if you want to be clever about, you know, you can do things. Like, for example, CMP uh, yea, ex, um, capital A. Yeah. And then you can dio, um let's go on, make an equal label here, right? Equal. Yeah. So if it's equal will return zero. Yeah. Um, otherwise, uh, otherwise will go to end, and we'll just put one. Yeah, And here we you know, we could go. Poppy, BP rats. Yeah, that You see how this works, right? So then we can go j e from weaken. Go. J e um, equal on here. We can go jump engines. Right? This could probably written a little better. It's just a simple example to show you. And if you If you assemble that apology in a tight main type of key? All right. So it will be better to show you this if we make it so. Outputs an insecure instead. So I'm just gonna change that percent. I re compile a now type a U C zero type B. You see one type. See, you see one type a u C. Zero. So if we go back to fouled up a sm, you know, you can see it gets the chop it calls. Get Shaw, which fills the X register with the character they pressed. And then here we we compare it with a capital A right. If it's equal to that, then we jump to equal, which will pull out which will run. Start running the CO from here and imagine set e X registered a zero, essentially returning zero to the caller of us. We just popped the base point are often return from the subroutine Right on. Obviously, if it is a if it is not a, then this jump equal never be will never jump on. Then the next instruction run or be jump end which will jump all the way over equal start running from here on. Then it will just put one in the X Register, which is true. Then it pops the base pointer off and and finally returns with subroutine as well. So I mean that, you know, that's how it works. This is assembly. 26. Conclusion: Hey, so you just finished the course? Congratulations. Hopefully now you know a lot more by assembly language. If you think something's being missing or there's something else you want to know, please drop me a message and I'll be sure to add a new lecture to the course to cover that so well done. Hope you found the course useful.