Check out a free preview of the full Web Assembly (Wasm) course
The "Stack & OpCode" Lesson is part of the full, Web Assembly (Wasm) course featured in this preview video. Here's what you'd learn in this lesson:
Jem explains Web Assembly is a stack machine which means all the instructions are either pushed or popped off a stack in a linear fashion. Operation Codes, or OpCodes, are readable computer instructions for representing machine language instructions.
Transcript from the "Stack & OpCode" Lesson
[00:00:00]
>> So before we get to anything more complicated, we have to understand some things about how WebAssembly is executed and how we get those instructions. So we're gonna talk about the Stack and Opcodes. WebAssembly is a Stack machine, that is everything that happens is either pushed or popped off a Stack.
[00:00:26]
And we can only have so much or we can only have so much information in the Stack at once. This seems similar you're probably Jam I know Stack that I've taken all the front end masters courses on data structures and operating algorithms things like that. This is a different Stack, the Stack that you're probably thinking of it's a data structure.
[00:00:46]
in JavaScript, we usually use an array to represent it, it uses lasting first out. This is not that, this is a machine Stack, as in, we load variables. So actually, let's go back to our other example. So in this case with git local, it's pushing that number onto the Stack.
[00:01:07]
So that primary patch then it pushes onto the Stack. So now we now have a pointer to this number that we passed in. And then it just returns that pointer. And fortunately during the compilation process it, it writes it to memory. And then JavaScript when we use it, it pulls that back out of memory.
[00:01:23]
And that's what's happening under the hood here. But everything we see in WebAssembly is pushing and popping off the Stack. That's it, that's all the commands we're gonna run. At its core, it's such a basic concept and it seems really really simple. But, we see the complexity in that, how do we do things like fore loops if it's just a Stack?
[00:01:50]
How do we do things like trying to think of more, it's difficult to do more complex engineering when it's only pushing and popping information off the Stack, and we can only do that one at a time. This is also different than the call Stack that you know of in JavaScript, which is a similar concept.
[00:02:13]
But again, it's different because JavaScript is not a Stack machine. It uses a heap, for its data underlying data structure. Versus WebAssembly, which only has a Stack which has this really tiny portion of memory. It's always reading and pulling from the memory and doing all the operations internally.
[00:02:29]
That is part of what makes assembly so fast, is that it doesn't have to worry about garbage collection. It doesn't have to worry about memory that's been dereferenced or anything like that, because it's all just a really simple right here right now. What's on my Stack? Pushing and popping.
[00:02:46]
Okay, I won't go too much more into the sack. But when we get to a more complicated example, which we do later, you'll see exactly what I mean. Opcodes. Remember how I said that all computer instructions at its core are just numbers and the numbers represent something based on the architecture on the CPU that we're using.
[00:03:08]
So in this case, probably an x86. x86 has a whole bunch of instructions, and at the core just numbers. So when we say something like get which, like get local or something like that, that corresponds to a specific hex code, which corresponds to a specific machine instruction. Yeah, we're low down we are [LAUGH] We are down here in the CPU in this low level code.
[00:03:36]
But because WebAssembly is designed to be friendly, we have Opcodes, which are just representations of these hex codes which are actually just machine level codes. But because we can't read hex that well, [LAUGH] We have these helpful Opcodes. Think of an Opcode as just a computer instruction code, but we call it Opcode code shorter.
[00:03:58]
Actually here is a really cool interactive table. And I know cool is completely relative. [LAUGH] But I think it's pretty cool, but it is. Okay. Loaded, is that big enough everybody see, though small I can only make it so big and see the whole table but. Alright, so here is a list of all of the WebAssembly opcodes.
[00:04:23]
So this is a list of all of the possible instructions that we can perform in WebAssembly, which is pretty cool. Because it fits in a table. It's a large table. Yes, but it fits in a table versus if we looked at all the possible instructions we can do in JavaScript, it would be hundreds of pages long.
[00:04:42]
WebAssembly is much simpler. With that simplicity, we get more complexity because we have less obfuscation, but at the core of it, these are everything we're gonna do is using one of these operation codes. So one of these instruction codes. Opcodes are based exactly on the type of number that we're dealing with.
[00:05:04]
Today we're only doing dealing with 32 bit integers. So all four opcodes are prefixed with I 32. But you also do 64 bit integers, floating point numbers, things like that. Let me pick one and we'll hover over it, I'll pick an easy one. Less than greater than add, adds an easy one equal and or think multiply.
[00:05:34]
Yep. So the way to read this is I because it's a Stack machine, the Stack is gonna take the last two things off the Stack. So it's gonna pop the last two numbers that are on the Stack and then perform an operation and it's going to return. It's gonna multiply those numbers together and it's going to return a 32 bit integer.
[00:05:55]
The shortcut or the actual machine instruction that we're calling is 0X6C. For a 32 bit integer, but because that would be tedious to write and it wouldn't make any sense. We say I 32 dot multiply. And there's also a multiply for 64 bit integers, floating point, numbers, etc.
[00:06:18]
Due to the portability of WebAssembly and the fact that it's gonna run on many platforms, we have this such specificity when it comes to operations. So it's a good time to give another shout out to JavaScript, which does all this stuff for you. You don't have to worry about types.
[00:06:34]
It does type conversion for you. If you wanna deal with integers or floating point numbers, it does all that for you. You can multiply, divide, add, you don't care about the underlying memory, architecture. But because we're writing WebAssembly, we do care. And we have to be very explicit about what we're doing because we're literally telling the computer what to do, how to move these bits of data around.
[00:06:53]
Thus the specificity. Again, if I showed you this table in the beginning, you'd be like what? What? Translate what? It's not really working. Okay, so this is a helpful reference. I won't even show you the official WebAssembly docs, cuz remember I showed you earlier and it's just like this jumble of information.
[00:07:14]
This to me is probably one of the more useful sites you're gonna use in terms of what can and can't you do in WebAssembly. And this tells you everything you can do, so it's a bit harder to read but so lt dash S is less than, but it's unsigned.
[00:07:31]
So we're talking about sign in unsigned integers earlier, subtraction, multiplication, things like that. And we can declare, and just real quick cuz this isn't quite an operation, it's an operation but it doesn't actually do anything. If we wanna declare just a number, we would say I 32.const, and then at that point we're pushing a 32-bit integer onto the Stack.
[00:07:55]
I forgot the name of the person who wrote this page, but shout out to them because they took a lot of really hard to understand information and put it into a nice table format. So, shout out to Pengo Ray. Don't know who you are but respect. All right, And interactive table that we talked a bit earlier about 32 bit integer, 64 bit integers.
[00:08:20]
Okay. So, because we're talking about WebAssembly is a Stack machine. And we're always pushing and popping from the Stack. We take this example of a multiplication example, we get local one. Remember the locals are the variables, we're passing into a function. And then we get local, or we get local 0 because it's zero index.
[00:08:41]
We get local 1. We can use 1 or 0, or we can use the actual name of the parameters themselves. I like to use the name of the parameters because, well, again, I write code to be readable by other humans. But if you want, you can get them in order.
[00:08:57]
So if we add three parameters, we're passing through a function, we can say get local zero, get a local one, get local two, and it's the same thing or you can call them by name directly. And then we multiply. And this right here is it's a little confusing because when you just look at it if you had no idea what I just said 20 minutes ago, you look at it and you're, wait, what operations being performed?
[00:09:22]
Because in JavaScript, if you wanna multiply two numbers, it would be number 1, times number 2, output something. But in WebAssembly, that is all implied you have to understand what's being pushed in pop to the Stack at all times. And you have to understand that this operation is gonna pull both values in the Stack and multiply them together.
[00:09:41]
If it seems I'm spending a lot of time on it, it's because as a JavaScript engineer, it's not intuitive to me what's happening. It's kind of the first time you see. Someone help me on the chat. What's it called when it's like 2, 2 an a plus, we're saying that my CS teachers.
[00:10:06]
I'm blanking right now, I'll think of it later. But it's really good binary. But it's a different way of looking at operations instead of doing operation number. Now, we're just purely using Stack. And these are all just pointers to memory, and then that computer instruction reads from those two pointers, executes them, and then clears the Stack.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops