We covered a lot so far that built the foundation for working with assembly, but so far we haven’t learned about the different instructions that are used to write an assembly program. Remember our warmup code? We used the mov and add instructions there. In this section, we dive deeper into those instructions.
You may say: “Why now?” Well, let me give you some context. To work with assembly language, we need 2 things (there’s more in reality, but for now these two are enough):
Registers & Memory
Instructions
You can see we already learned about different types of registers and memory addressing modes. The only thing left was instructions—so that’s what we tackle now.
Registers and memory are where we store data, but what do we do with that data? That’s where instructions come in. Using instructions, we work with the data and perform operations to solve specific problems. I hope that makes sense?
When we talk about instructions, it’s better to address one thing early: because assembly language is a low-level representation of machine language, it is tightly coupled to the CPU design. There are many CPU vendors out there, and each of them has its own way of doing things. Because of that, there is no single universal set of assembly instructions.
Let’s suppose we are very familiar with assembly programming. Still, one day you might come across an instruction that looks completely new. Why? Because that instruction is valid only for a specific vendor’s processor. In that case, we need to check that vendor’s documentation. Don’t worry—it’s not as hard as it sounds. If you understand the basics of assembly (what we are learning now), then adapting to a new instruction set is much easier.
Now, here’s the good news: while some instructions are vendor-specific, there are common categories of instructions that exist in almost every assembly language. And these are enough for us to start writing assembly programs as beginners. These categories are:
Data Transfer Instructions
Arithmetic and Logic Instructions
Control Flow Instructions
System Control Instructions
Data Transfer Instructions
Explanation of all the data transfer instruction are written below:
Move Instruction (mov):
The MOV instruction, as discussed earlier, is used to transfer data from a source to a destination.
Source: where the data comes from. This can be a constant (immediate value), a register, or a memory location/variable.
Destination: where the data goes. This can be a register or a memory location.
Important to remember: you cannot directly move data from one memory location to another (memory-to-memory move). Data must go through a register first.
Logical Flow
When the CPU sees a MOV instruction, here’s what it does step by step:
Reads the source operand (value, register, or memory).
Copies that value into the destination operand.
The source remains unchanged — only the destination gets updated.
Syntax
mov <Destination>, <Source>
<Destination> = Required. Where the value will be placed (register or memory).
<Source> = Required. What value is being copied (constant, register, or memory).
Examples
mov ax, 6 ; Move immediate value 6 into AX
mov var1, bx ; Move value from BX into memory location var1
mov bx, var1 ; Move value from memory location var1 into BX
mov ax, bx ; Move value from ax into bx - very fast
Tip: If both operands are registers, the transfer happens very fast (since no memory or buses are involved). If one operand is memory, the CPU has to go through system buses, which makes it slower.
PUSH & POP
I admit I haven’t explained the stack much yet. In the stack register section we touched on this topic a little bit, and I mentioned we’d go through it later because we hadn’t yet reached the point where we work with the stack.
Right now, we are still learning the basics — and the stack is a topic of its own kind. We will cover it fully later, but for now go and revise the stack register section again, because there I covered a little bit about the stack. Here, we’ll just focus on two instructions used to work with it.
Push Instruction (PUSH)
The PUSH instruction is used to store data onto the stack.
Syntax
push <Source>
Source: Required. Can be a register or a memory operand.
Destination: Always the stack (handled internally by the CPU, not by us).
Logical Flow
The Stack Pointer (SP) register decreases by 2 (in 16-bit mode).
The CPU copies the source operand into the memory location now pointed to by SP.
Examples
push ax ; Push AX register value onto stack
push bx ; Push BX register value onto stack
push var1 ; Push the value of memory variable var1 onto stack
Pop Instruction (POP)
The POP instruction is used to retrieve data from the top of the stack and place it into a destination.
Syntax
pop <Destination>
Source: Always the stack (handled internally by the CPU).
Destination: Required. Can be a register or a memory operand where the popped value will be stored.
Logical Flow
The CPU reads the value stored at the memory location currently pointed to by SP.
That value is copied into the destination operand.
The Stack Pointer (SP) register increases by 2 (restoring the stack to its previous state).
Examples
pop ax ; Pop the top value from stack into AX
pop bx ; Pop the top value from stack into BX
pop var1 ; Pop the top value from stack into memory variable var1
IN & OUT
Just like with the stack, I haven’t explained I/O ports yet. That’s a whole topic of its own, and we’ll study it later when we talk about input/output devices.
For now, you only need to know the instructions that allow us to transfer data between the CPU and I/O ports. Don’t stress about what a port really is right now — we’ll cover that later. Just cram the behavior of these instructions.
In Instruction (IN)
The IN instruction is used to read data from an I/O port into a register.
Syntax
in <Destination>, <Port>
Destination: Required. Must be AL, AX, or EAX depending on the data size.
Port: Required. The I/O port address, which can be an immediate value or stored in DX.
Logical Flow
The CPU places the port address on the address bus.
Data from that port is read and transferred into the destination register.
Examples
in al, 60h ; Read data from port 60h into AL
in ax, dx ; Read data from the port whose address is in DX into AX
Note: Don’t worry if I/O ports sound confusing right now. Later we’ll cover exactly what ports are and how they are used. For now, just remember that IN moves data from a port → into a register.
Out Instruction (OUT)
The OUT instruction is the opposite of IN. It is used to send data from a register to an I/O port.
Syntax
out <Port>, <Source>
Port: Required. The I/O port address, which can be an immediate value or stored in DX.
Source: Required. Must be AL, AX, or EAX depending on the data size.
Logical Flow
The CPU takes the value from the source register.
That value is sent to the specified port address through the data bus.
Examples
out 60h, al ; Send the value in AL to port 60h
out dx, ax ; Send the value in AX to the port whose address is in DX