# Assembly Instructions

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):

1. Registers & Memory
2. 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:

1. Data Transfer Instructions
2. Arithmetic and Logic Instructions
3. Control Flow Instructions
4. System Control Instructions

<details>

<summary>Data Transfer Instructions</summary>

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:

  1. Reads the **source operand** (value, register, or memory).
  2. Copies that value into the **destination operand**.
  3. The source remains unchanged — only the destination gets updated.

  **Syntax**

  ```nasm
  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**

  ```nasm
  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
  ```

{% hint style="info" %}
**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.
{% endhint %}

***

* **PUSH & POP**

{% hint style="info" %}
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.
{% endhint %}

**Push Instruction (`PUSH`)**

The `PUSH` instruction is used to store data onto the **stack**.

**Syntax**

```nasm
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**

1. The **Stack Pointer (SP)** register decreases by 2 (in 16-bit mode).
2. The CPU copies the source operand into the memory location now pointed to by SP.

**Examples**

```nasm
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**

```nasm
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**

1. The CPU reads the value stored at the memory location currently pointed to by SP.
2. That value is copied into the destination operand.
3. The **Stack Pointer (SP)** register increases by 2 (restoring the stack to its previous state).

**Examples**

```nasm
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**

{% hint style="info" %}
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.
{% endhint %}

**In Instruction (`IN`)**

The `IN` instruction is used to read data from an **I/O port** into a register.

**Syntax**

```nasm
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**

1. The CPU places the port address on the address bus.
2. Data from that port is read and transferred into the destination register.

**Examples**

```nasm
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
```

{% hint style="info" %}
***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.*
{% endhint %}

**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**

```nasm
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**

1. The CPU takes the value from the source register.
2. That value is sent to the specified port address through the data bus.

**Examples**

```nasm
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
```

***

</details>
