Introduction to Assembly

Introduction

Assembly language, often referred to as ASM, is a low-level programming language that serves as a bridge between machine code and high-level programming languages. It provides a way to write programs with a direct correspondence to the underlying machine instructions executed by the CPU. This direct relationship makes assembly language highly efficient but also more intricate compared to high-level languages like Python or Java.


Why Learn Assembly Language?

Performance

Assembly language allows for highly optimized code, giving you the ability to fine-tune the performance of your programs. By writing in assembly, you can exploit specific features of the CPU architecture to achieve maximum speed and efficiency.

Control

With assembly language, you gain complete control over the hardware. This allows you to manipulate and optimize system resources in ways that high-level languages abstract away, providing a deeper understanding of hardware operations.

Understanding

Learning assembly language offers valuable insights into how the CPU and memory interact at a fundamental level. This knowledge is crucial for tasks such as debugging low-level software issues, optimizing performance, and understanding how higher-level languages are executed.


Basic Concepts

Registers

Registers are small, fast storage locations within the CPU used to perform operations and store intermediate data. Common registers include:

  • AX: Accumulator Register, used for arithmetic operations.
  • BX: Base Register, often used for addressing.
  • CX: Count Register, typically used for loops and shift operations.
  • DX: Data Register, used for I/O operations.

Memory

In assembly language, memory is accessed using addresses. Instructions can load data from specific memory addresses into registers or store data from registers into memory locations. This direct memory manipulation allows for precise control over data storage and retrieval.

Instruction Set

The instruction set is the collection of commands that the CPU can execute. These instructions typically perform operations like data movement, arithmetic, and control flow.


Basic Instructions

Data Movement

  • MOV: Transfers data from one location to another.
MOV AX, 5    ; Load the value 5 into the AX register
MOV BX, AX   ; Copy the value from AX into BX

Arithmetic

  • ADD: Adds two values.
ADD AX, BX   ; Add the value in BX to AX
  • SUB: Subtracts one value from another.
SUB AX, 2    ; Subtract 2 from the value in AX

Control Flow

  • JMP: Jumps to a different part of the program.
JMP LABEL    ; Jump to the instruction labeled "LABEL"
  • CMP: Compares two values.
CMP AX, BX   ; Compare AX with BX
  • JE: Jumps if the comparison was equal.
JE EQUAL_LABEL   ; Jump to "EQUAL_LABEL" if AX equals BX

XMM Registers

XMM registers are part of the SIMD (Single Instruction, Multiple Data) extensions in the x86 architecture, starting with SSE (Streaming SIMD Extensions). These registers are designed to handle floating-point operations and vectorized data processing, which can significantly enhance performance for applications that require complex mathematical computations, such as graphics processing and scientific simulations.

Register Types and Evolution

128-bit XMM Registers

  • XMM0 to XMM7: Introduced with SSE and SSE2, these 128-bit registers are used to perform parallel operations on multiple data elements. They are essential for handling vectorized operations, allowing simultaneous processing of multiple data points.

256-bit YMM Registers

  • YMM0 to YMM7: Introduced with AVX (Advanced Vector Extensions), these registers extend the XMM registers to 256 bits. This allows for operations on larger data sets and more complex vector calculations, enhancing performance for applications requiring extensive data manipulation.

512-bit ZMM Registers

  • ZMM0 to ZMM7: Introduced with AVX-512, these 512-bit registers further extend the SIMD capabilities, providing even more power for handling large datasets and performing advanced vector operations.

Key Features

  • Parallel Processing: XMM, YMM, and ZMM registers enable parallel processing of multiple data elements, improving the efficiency of operations like matrix multiplications, graphics rendering, and numerical simulations.
  • Enhanced Performance: SIMD instructions allow for the simultaneous execution of the same operation on multiple pieces of data, which can drastically improve performance compared to scalar operations.
  • Extended Data Width: The extension from 128-bit to 256-bit and 512-bit registers allows for more data to be processed in a single instruction, further boosting performance for data-intensive tasks.

Basic SIMD Instructions

Data Movement

  • MOVAPS: Moves packed single-precision floating-point values.
MOVAPS XMM0, [Symbol]  ; Load 128-bit data from "Symbol" into XMM0

Arithmetic Operations

  • ADDPS: Adds packed single-precision floating-point values.
ADDPS XMM0, XMM1  ; Add packed values in XMM1 to those in XMM0
  • SUBPS: Subtracts packed single-precision floating-point values.
SUBPS XMM0, XMM1  ; Subtract packed values in XMM1 from those in XMM0

Comparison

  • CMPPS: Compares packed single-precision floating-point values.
CMPPS XMM0, XMM1, 0  ; Compare packed values in XMM0 and XMM1 with the specified comparison mode

Cheat Engine Example

label(code return)
label(Enemy Player)

newmem:
  ; Load value from memory address [rbx + 0xB0] into rax
  mov rax,[rbx+000000B0]   
  ; Test if rax is zero
  test rax,rax              
  ; Jump to 'code' if rax is zero
  jz code                   

  ; Load value from [rax + 0x240] into rax
  mov rax,[rax+00000240]   
  ; Test if rax is zero
  test rax,rax              
  ; Jump to 'Enemy' if rax is zero
  jz Enemy                  
  ; Jump to 'Player' if not zero
  jmp Player                

Enemy:
  ; Set address for Enemy's Health Decrement Pointer
  mov [HealthDec+8],rbx    
  ; Compare flag for Enemy
  cmp byte ptr [HealthDecFlag+1],0 
  ; Jump to 'code' if flag is 0
  je code                   

  ; Compare flag for Enemy
  cmp byte ptr [HealthDecFlag+1],1 
  ; Jump to label '@f' if not equal
  jne @f                   
    ; Move scalar single-precision float from xmm0 to xmm1
    movss xmm1,xmm0         
    ; Jump to 'code'
    jmp code               
  ; Label '@f' continuation
  @@:
  ; Compare flag for Enemy
  cmp byte ptr [HealthDecFlag+1],2 
    ; Multiply xmm1 with value at [HealthDecMultiplier + 4]
    mulss xmm1,[HealthDecMultiplier+4] 
  ; Jump to 'code'
  jmp code                   
  ; Reset flag to 0
  mov byte ptr [HealthDecFlag+1],0 

Player:
  ; Set address for Player's Health Decrement Pointer
  mov [HealthDec],rbx      
  ; Compare flag for Player
  cmp byte ptr [HealthDecFlag],0 
  ; Jump to 'code' if flag is 0
  je code                   

  ; Compare flag for Player
  cmp byte ptr [HealthDecFlag],1 
  ; Jump to label '@f' if not equal
  jne @f                   
    ; Zero out xmm1
    xorps xmm1,xmm1        
    ; Jump to 'code'
    jmp code               
  ; Label '@f' continuation
  @@:
  ; Compare flag for Player
  cmp byte ptr [HealthDecFlag],2 
    ; Multiply xmm1 with value at [HealthDecMultiplier]
    mulss xmm1,[HealthDecMultiplier] 
  ; Jump to 'code'
  jmp code                   
  ; Reset flag to 0
  mov byte ptr [HealthDecFlag],0 

code:
  ; Subtract xmm1 from xmm0
  subss xmm0,xmm1         
  ; Compare xmm0 with xmm7
  comiss xmm0,xmm7        
  ; Jump to the return address
  jmp return                

; Memory addresses and flags
HealthDec:
 dq 0 ; Player                 
 dq 0 ; Enemy                  

HealthDecFlag:
 db 2 ; Player                 
 db 2 ; Enemy                  

HealthDecMultiplier:
 dd (float)0.25 ; Player       
 dd (float)2.00 ; Enemy        

; Register symbols for cheat table
registersymbol(HealthDecHook HealthDec HealthDecFlag HealthDecMultiplier)

Further Reading:

To dive deeper into assembly language and related topics, explore the following resources:

1 Like