In order to efficiently store opcodes, they are encoded to bytecode. Every opcode is allocated a byte (for example; STOP is
0x00). Let’s take a look at the following bytecode:
During execution, bytecode is split up into its bytes (1 byte equals 2 hexadecimal characters). Bytes in range 0x60–0x7f (PUSH1-PUSH32) are treated differently because they include push data (which needs to be attached to the opcode, instead of being treated as a separate opcode).
The first instruction is
0x60 which translates to PUSH1. Therefore, we know the push data is 1 byte long, and we add the next byte to the stack. The stack now contains 1 item, and we can move to the next instruction. Since we know
0x01 is part of a PUSH instruction, the next instruction we need to execute is another
0x60 (PUSH1) along with the same data. The stack now contains 2 identical items. The final instruction is
0x01, which translates to ADD. This instruction will take 2 items from the stack, and pushes the sum of these items to the stack. The stack now contains one item: