ASM Instructions

ASM Instructions

Start learning basic instructions in Assembly.

Here are some important x86 assembly language instructions you need to learn:

mov - This is the move instruction. It is used to move data from one register or memory location to another register or memory location.

add - This is the add instruction. It is used to add two operands and store the result. The operands can be registers or memory locations.

sub - This is the subtract instruction. It subtracts one operand from another and stores the result.

jmp - This is the jump instruction. It is used to change the flow of execution by jumping to another location in the program.

call - This is the call instruction. It is used to call subroutines or functions. It saves the return address on the stack and then jumps to the given subroutine.

cmp - This is the compare instruction. It compares two operands and sets the status flags based on the result but does not store the result.

push - This pushes a value onto the stack.

pop - This pops a value from the stack.

xor - This is the exclusive OR instruction. It performs a logical XOR operation on the operands.

and - This performs a logical AND operation on the operands.

These are some of the most commonly used x86 assembly language instructions. You will need to learn about their syntax, operands, usage scenarios, and how to use them in assembly language programs.


Move

Here is a explanation of the mov instruction in x86 assembly language:

mov - The mov instruction is used to move or copy data from one place to another. It has two main forms:

mov source, destination mov source_register, destination_register

The source can be:

  • An immediate value

  • A register

  • A memory location

The destination can be:

  • A register

  • A memory location

Use cases:

  • Copying an immediate value to a register: mov eax, 10 This copies the decimal value 10 to the eax register.

  • Copying from one register to another:
    mov ebx, eax This copies the value in eax to ebx.

  • Copying from memory to a register: mov eax, [variable] This copies the value stored at the memory location variable to eax.

  • Copying from a register to memory: mov [variable], ebx
    This copies the value in ebx to the memory location variable.

So in summary, the mov instruction is used to copy values between registers and memory locations, allowing you to move data around in assembly language programs. Let me know if you need any clarification or have more questions!


Examples

Here is an explanation of variables and an example of mov instruction in x86 assembly code:

Variables in Assembly: Variables in assembly language are represented by memory locations. When you declare a variable, you are reserving a block of memory that can store a value.

To use a variable in assembly code, you first need to define it using the .data directive:

.data variable1: .byte 1 ; Define a byte variable variable2: .word 2 ; Define a word (2 byte) variable

You can then access the variable's memory location using the [] notation:

[variable1] [variable2]

Let's define two byte variables and copy one to the other using mov:

  .data
  num1: .byte 0   
  num2: .byte 0

  .code    
  mov al, 10h ; Load al register with 10h
  mov [num1], al ; Move value from al to num1  
               ; num1 now stores 10h

  mov al, [num1] ; Move value from num1 to al
                ; al now stores 10h

  mov [num2], al ; Move value from al to num2  
               ; num2 now also stores 10h

Here we:

  1. Defined two byte variables - num1 and num2

  2. Loaded the al register with a value

  3. Moved that value to num1 using mov [num1], al

  4. Copied the value from num1 to al

  5. Finally moved that value to num2

So variables in assembly are represented by memory locations that you define. The mov instruction is used to copy values between registers and variables.

Syntax Notes:

This code fragment contains some x86 assembly code:

  • Lines that start with a . are directives that provide assembly time information. These include:

    • .data : Indicates the start of the data section where variables are defined

    • .byte : Defines a byte sized variable

    • .word : Defines a word (2 byte) sized variable

    • .code : Indicates the start of the code section where instructions go

  • Lines that start with mov are assembly instructions that move data.

  • Lines that end with ; are comments that provide information about the instruction on that line.

So in summary:

  • .data, .byte, .word, .code - Are assembly directives

  • mov - Is an assembly instruction

  • ; - Starts a comment

We will explain more syntax elements as we go, using examples of code for each common statment. For now I think is good enaugh to start reading Assembly examples.


Add

The add instruction is used to perform addition on registers and memory locations. We can add either two registers or a register and a memory location.

.data
num1: .byte 5
num2: .byte 10
result: .byte 0

.code
mov al, [num1]
mov bl, [num2]
add al, bl 
mov [result], al

The add instruction in assembly is used to add two values. In this example, we are adding the values stored in num1 and num2 and storing the result in result.

In detail:

  • We define 3 byte variables: num1, num2 and result

  • We load the values from num1 (5) and num2 (10) into the al and bl registers respectively

  • We use the add instruction to add the values in al and bl. This results in 15.

  • We store the result (15) in the result variable using mov [result], al

Notes: HashNode syntax color is not possible for Assembly. Therefore this code is completly white. I will try to use other method to sow some more advanced code later with syntax color.

The add instruction cannot directly store data in memory. It can only add values in registers. To store the result of an addition in memory, we need to use a separate instruction like mov.

In x86 assembly, the main instructions that can store data in memory are:

  • mov - The mov (move) instruction can move data from a register to memory or from memory to a register. We used mov [result], al to store the result in al to the result memory location.

  • push - The push instruction pushes a value onto the stack. It decrements the stack pointer and stores the value at the new stack location.

  • pop - The pop instruction pops a value from the stack. It reads the value from the current stack location and increments the stack pointer.

  • lea - The lea (load effective address) instruction stores a memory address in a register.

  • stos - The stos (store string) instruction stores a string in memory.

So in summary:

  • The add instruction can only add values in registers. It cannot directly store the result in memory.

  • We used the mov instruction to move the result from the al register to the result memory location after performing the addition.

  • Without using a register to store the result and then moving it to memory, we cannot store the result of an addition directly in memory.

Clarifications:

Data must first be moved into registers before operations can be performed. The addition is done in the al and bl registers. The result overwrites the original values and is stored in al. We use mov to store the result in al to memory at [result]. If we want to use the result a second time, we must either reload it from memory into a register, or keep it in al and use it directly, losing the original values in al and bl.

Important to know:

The mov instruction does not actually "move" data - it makes a copy of the data. The original data remains intact after the mov instruction.

When we use mov to store a register value to memory, like mov [result], al, what happens is:

  1. The processor copies the value currently in the al register.

  2. It then writes that copied value to the memory location result.

The original value in the al register remains unchanged. It is not "moved" from the register to memory - a copy of the value is made and written to memory, while the original value in the register remains intact.

Similarly, when we use mov to load a memory value into a register, like mov al, [result], what happens is:

  1. The value from the memory location result is copied.

  2. That copied value is then written to the al register.

The original value in memory at [result] remains unchanged. It is not "moved" from memory to the register - a copy of the value is made and written to the register, while the original value in memory remains intact.

So in summary, the mov instruction makes a copy of data and writes that copy to the destination. The original data in the source (register or memory) remains unchanged.


The sub instruction subtracts one operand from another and stores the result. Here is an example:

  mov al, 10 ; Load al register with 10
  mov bl, 5  ; Load bl register with 5 
  sub al, bl ; Subtract bl from al. al now contains 10 - 5 = 5

After the sub instruction, al contains the result of the subtraction (10 - 5 = 5) and bl still contains 5.

Some clarifications:

  • The sub instruction subtracts the second operand from the first. In our example, we subtracted bl from al.

  • The result is stored in the first operand (the destination operand). In our example, the result 5 is stored in al.

  • The second operand (the source operand) remains unchanged. In our example, bl still contains 5 after the subtraction.

  • Both operands can be either registers or memory locations. For example:

mov ax, 10
mov [number], 5 sub ax, [number] ;Subtract memory from register
  • The sub instruction can also subtract an immediate value. For example:
mov ax, 10 sub ax, 5 ;Subtract 5 from ax. ax now contains 10 - 5 = 5

Limitations

The add and sub instructions in assembly language can handle:

  • Integer data: They can add and subtract integers of 8-bit, 16-bit or 32-bit sizes depending on the registers or memory operands used. For example:
add al, bl ; Add 8-bit integers in al and bl  
add ax, bx ; Add 16-bit integers in ax and bx
add eax, ebx ; Add 32-bit integers in eax and ebx
  • Binary data: They can add and subtract binary data stored in registers or memory. This is useful for manipulating raw binary data.

  • BCD data: They can add and subtract packed BCD (Binary Coded Decimal) data. Packed BCD uses 4 bits to represent one decimal digit.

  • Hex data: They can be used to manipulate data represented in hexadecimal format.

So in summary, the add and sub instructions can perform arithmetic on:

  • Integer data of various sizes

  • Binary data

  • BCD data

  • Hexadecimal data

The main limitation is that they perform binary arithmetic, so they are not suitable for floating point data which uses a different representation. For floating point addition and subtraction, you would need to use the floating point add and subtract instructions specific to the processor.


add & sub

Here are some common use cases and best practices for the add and sub instructions:

Use Cases:

  • Incrementing/decrementing counters: Using add and sub to increment or decrement counters is a common use case. For example:
mov cx, 0  ; Initialize counter

loop:
    ; Some code
    add cx, 1 ; Increment counter 
    cmp cx, 10 ; Compare counter with 10
    jl loop ; Loop until counter is less than 10
  • Performing arithmetic calculations: Add and sub are used to perform basic arithmetic operations like addition, subtraction, multiplication and division.

  • Manipulating binary data: Add and sub can be used to manipulate raw binary data stored in registers or memory.

Best Practices:

  • Use the appropriate size registers based on the data: Use 8-bit registers for 8-bit data, 16-bit registers for 16-bit data and so on. This ensures optimal performance.

  • Avoid overflow: Check if the result will cause an overflow before performing the operation. Handle overflow conditions appropriately.

  • Clear carry flag after using it: If the carry flag is used, make sure to clear it after the operation to avoid unintended effects on subsequent instructions.

  • Optimize for performance: On some processors, using larger registers (32-bit or 64-bit) can give better performance than smaller registers (8-bit or 16-bit).

  • Use immediate operands where possible: Using an immediate value as an operand is usually faster than accessing memory.

Hope these use cases and best practices for the add and sub instructions help you to think like a professional coder. We encourage young developers to learn how to avoid mistakes hard to find in a large Assembly code-base!


Disclaimer: This article was created with the assistance of an AI chatbot. The information provided may contain inaccuracies and should not be fully relied upon. Please conduct your own research and verification before citing any information from this article.