Web Assembly (Wasm) Stack & OpCode
Transcript from the "Stack & OpCode" Lesson
>> 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: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: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: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: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: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.