Matter AI | Code Reviewer Documentation home pagelight logodark logo
  • Contact
  • Github
  • Sign in
  • Sign in
  • Documentation
  • Blog
  • Discord
  • Github
  • Introduction
    • What is Matter AI?
    Getting Started
    • QuickStart
    Product
    • Security Analysis
    • Code Quality
    • Agentic Chat
    • RuleSets
    • Memories
    • Analytics
    • Command List
    • Configurations
    Patterns
    • Languages
      • Supported Languages
      • Python
      • Java
      • JavaScript
      • TypeScript
      • Node.js
      • React
      • Fastify
      • Next.js
      • Terraform
      • C#
      • C++
      • C
      • Go
      • Rust
      • Swift
      • React Native
      • Spring Boot
      • Kotlin
      • Flutter
      • Ruby
      • PHP
      • Scala
      • Perl
      • R
      • Dart
      • Elixir
      • Erlang
      • Haskell
      • Lua
      • Julia
      • Clojure
      • Groovy
      • Fortran
      • COBOL
      • Pascal
      • Assembly
      • Bash
      • PowerShell
      • SQL
      • PL/SQL
      • T-SQL
      • MATLAB
      • Objective-C
      • VBA
      • ABAP
      • Apex
      • Apache Camel
      • Crystal
      • D
      • Delphi
      • Elm
      • F#
      • Hack
      • Lisp
      • OCaml
      • Prolog
      • Racket
      • Scheme
      • Solidity
      • Verilog
      • VHDL
      • Zig
      • MongoDB
      • ClickHouse
      • MySQL
      • GraphQL
      • Redis
      • Cassandra
      • Elasticsearch
    • Security
    • Performance
    Integrations
    • Code Repositories
    • Team Messengers
    • Ticketing
    Enterprise
    • Enterprise Deployment Overview
    • Enterprise Configurations
    • Observability and Fallbacks
    • Create Your Own GitHub App
    • Self-Hosting Options
    • RBAC
    Patterns
    Languages

    Assembly

    Assembly language is a low-level programming language for a computer, or other programmable device, in which there is a very strong correspondence between the language and the architectures machine code instructions.

    Assembly language, despite being the closest programming language to machine code, has several common anti-patterns that can lead to bugs, maintainability problems, and performance issues. Here are the most important anti-patterns to avoid when writing Assembly code.

    ; Anti-pattern: Hardcoded memory addresses
    section .text
    global _start
    
    _start:
        mov eax, [0x12345678]    ; Hardcoded memory address
        add eax, 42
        mov [0x12345678], eax    ; Store back to hardcoded address
    
    ; Better approach: Use labeled memory locations
    section .data
    my_variable dd 0
    
    section .text
    global _start
    
    _start:
        mov eax, [my_variable]   ; Use symbolic reference
        add eax, 42
        mov [my_variable], eax   ; Store back using symbolic reference

    Avoid using hardcoded memory addresses. Instead, use labels and let the assembler/linker calculate the actual addresses. This makes your code more maintainable and relocatable.

    ; Anti-pattern: Insufficient comments
    section .text
    global _start
    
    _start:
        mov eax, 1
        mov ebx, 0
        int 0x80
    
    ; Better approach: Well-commented code
    section .text
    global _start
    
    ; Entry point of the program
    _start:
        mov eax, 1      ; System call number for exit()
        mov ebx, 0      ; Exit status code 0 (success)
        int 0x80        ; Call kernel to execute exit()

    Assembly code can be difficult to understand without proper comments. Document your code thoroughly, explaining the purpose of registers, memory operations, and the overall logic of your routines.

    ; Anti-pattern: Self-modifying code
    section .text
    global _start
    
    _start:
        ; Modify the instruction at runtime
        mov byte [instruction+1], 42  ; Change the immediate value
    
    instruction:
        mov al, 10                    ; This will be modified to mov al, 42
        ; Rest of the code...
    
    ; Better approach: Use data for configuration
    section .data
    config_value db 42
    
    section .text
    global _start
    
    _start:
        mov al, [config_value]        ; Load the value from data section
        ; Rest of the code...

    Avoid self-modifying code, which changes instructions at runtime. It makes debugging difficult, can cause cache coherency issues, and may not work on systems with memory protection. Instead, use data structures to store configurable values.

    ; Anti-pattern: Not preserving registers
    calculate_sum:
        mov eax, [ebx]        ; Load value from memory
        add eax, [ebx+4]      ; Add next value
        ret                   ; Return with sum in eax
    
    ; Better approach: Preserve registers according to calling convention
    calculate_sum:
        push ebx              ; Save registers that will be modified
        push ecx
        
        mov eax, [ebx]        ; Load value from memory
        add eax, [ebx+4]      ; Add next value
        
        pop ecx               ; Restore registers in reverse order
        pop ebx
        ret                   ; Return with sum in eax

    Follow the appropriate calling convention for your platform. Save and restore registers that your function modifies but are required to be preserved according to the calling convention.

    ; Anti-pattern: Spaghetti code with excessive jumps
    process_data:
        cmp eax, 0
        je zero_case
        cmp eax, 1
        je one_case
        jmp default_case
    
    zero_case:
        ; Handle zero case
        jmp end_process
    
    one_case:
        ; Handle one case
        jmp end_process
    
    default_case:
        ; Handle default case
        jmp end_process
    
    end_process:
        ret
    
    ; Better approach: Structured code with fewer jumps
    process_data:
        cmp eax, 0
        je zero_case
        cmp eax, 1
        je one_case
        
        ; Handle default case inline
        ; ...
        jmp end_process
    
    zero_case:
        ; Handle zero case
        jmp end_process
    
    one_case:
        ; Handle one case
        ; Fall through to end_process
    
    end_process:
        ret

    Minimize the use of jumps and labels to avoid creating “spaghetti code.” Structure your code in a way that follows logical flow and makes it easier to understand.

    ; Anti-pattern: Not using stack frames
    my_function:
        ; Directly manipulate the stack
        sub esp, 12           ; Allocate 12 bytes on stack
        mov [esp], eax        ; Save parameter
        mov [esp+4], ebx      ; Save another parameter
        
        ; Function body...
        
        add esp, 12           ; Deallocate stack space
        ret
    
    ; Better approach: Use stack frames
    my_function:
        push ebp              ; Save old base pointer
        mov ebp, esp          ; Set up new base pointer
        sub esp, 12           ; Allocate local variables
        
        mov [ebp-4], eax      ; Store local variable
        mov [ebp-8], ebx      ; Store another local variable
        
        ; Function body...
        
        mov esp, ebp          ; Restore stack pointer
        pop ebp               ; Restore base pointer
        ret

    Use proper stack frames (prologue and epilogue) for functions. This makes it easier to access parameters and local variables, and helps with debugging.

    ; Anti-pattern: Using magic numbers
    section .text
    global _start
    
    _start:
        mov eax, 4            ; What does 4 mean?
        mov ebx, 1            ; What does 1 mean?
        mov ecx, message
        mov edx, 13           ; What does 13 mean?
        int 0x80
    
    ; Better approach: Use constants or comments
    section .text
    global _start
    
    ; Constants
    SYS_WRITE equ 4
    STDOUT equ 1
    
    _start:
        mov eax, SYS_WRITE    ; System call number for write()
        mov ebx, STDOUT       ; File descriptor for standard output
        mov ecx, message      ; Pointer to message
        mov edx, message_len  ; Length of message
        int 0x80
    
    section .data
    message db "Hello, World!", 0
    message_len equ $ - message

    Avoid using “magic numbers” in your code. Define constants with meaningful names to make your code more readable and maintainable.

    ; Anti-pattern: Cache-unfriendly memory access
    process_matrix:
        mov esi, matrix       ; Pointer to matrix
        mov ecx, 1000         ; Number of rows
    
    row_loop:
        mov edi, 0            ; Column index
    
    col_loop:
        ; Access matrix in column-major order (cache-unfriendly)
        mov eax, [esi + edi*4000]  ; Access element at [row, col]
        ; Process element...
        
        add edi, 1            ; Next column
        cmp edi, 1000
        jl col_loop
        
        add esi, 4            ; Next row
        dec ecx
        jnz row_loop
        ret
    
    ; Better approach: Cache-friendly memory access
    process_matrix:
        mov esi, matrix       ; Pointer to matrix
        mov ecx, 1000         ; Number of rows
    
    row_loop:
        mov edi, 0            ; Column index
    
    col_loop:
        ; Access matrix in row-major order (cache-friendly)
        mov eax, [esi + edi*4]  ; Access element at [row, col]
        ; Process element...
        
        add edi, 1            ; Next column
        cmp edi, 1000
        jl col_loop
        
        add esi, 4000         ; Next row (assuming 1000 columns * 4 bytes)
        dec ecx
        jnz row_loop
        ret

    Be mindful of memory access patterns. Access memory sequentially when possible to take advantage of CPU caching and prefetching mechanisms.

    ; Anti-pattern: Not checking return values
    open_file:
        mov eax, 5            ; sys_open
        mov ebx, filename
        mov ecx, 0            ; O_RDONLY
        int 0x80
        ; No check if eax < 0 (error)
        
        mov [file_descriptor], eax
        ret
    
    ; Better approach: Check return values
    open_file:
        mov eax, 5            ; sys_open
        mov ebx, filename
        mov ecx, 0            ; O_RDONLY
        int 0x80
        
        cmp eax, 0
        jl open_error         ; Jump if negative (error)
        
        mov [file_descriptor], eax
        mov eax, 0            ; Return success
        ret
        
    open_error:
        mov eax, -1           ; Return error
        ret

    Always check return values from system calls and functions to handle error conditions properly.

    ; Anti-pattern: Using inefficient instructions
    clear_register:
        mov eax, 0            ; Clear eax
        mov ebx, 0            ; Clear ebx
        mov ecx, 0            ; Clear ecx
        mov edx, 0            ; Clear edx
        ret
    
    ; Better approach: Use appropriate instructions
    clear_register:
        xor eax, eax          ; Clear eax (faster and smaller)
        xor ebx, ebx          ; Clear ebx
        xor ecx, ecx          ; Clear ecx
        xor edx, edx          ; Clear edx
        ret

    Use the most appropriate instructions for each task. For example, xor reg, reg is faster and smaller than mov reg, 0 for clearing a register.

    ; Anti-pattern: Repeating common code patterns
    function1:
        push ebp
        mov ebp, esp
        ; Function body...
        mov esp, ebp
        pop ebp
        ret
    
    function2:
        push ebp
        mov ebp, esp
        ; Function body...
        mov esp, ebp
        pop ebp
        ret
    
    ; Better approach: Use macros
    %macro FUNCTION_PROLOGUE 0
        push ebp
        mov ebp, esp
    %endmacro
    
    %macro FUNCTION_EPILOGUE 0
        mov esp, ebp
        pop ebp
        ret
    %endmacro
    
    function1:
        FUNCTION_PROLOGUE
        ; Function body...
        FUNCTION_EPILOGUE
    
    function2:
        FUNCTION_PROLOGUE
        ; Function body...
        FUNCTION_EPILOGUE

    Use macros to encapsulate common code patterns. This reduces duplication and makes your code more maintainable.

    ; Anti-pattern: Unaligned data
    section .data
    value1 db 42
    value2 dd 12345           ; Might be unaligned
    
    ; Better approach: Aligned data
    section .data
    value1 db 42
    align 4                   ; Align to 4-byte boundary
    value2 dd 12345           ; Now properly aligned

    Ensure proper alignment of data structures. Unaligned memory access can cause performance penalties or even crashes on some architectures.

    ; Anti-pattern: Scalar operations for vector data
    process_array:
        mov ecx, 4            ; Process 4 elements
        mov esi, array
    
    loop_start:
        mov eax, [esi]        ; Load element
        add eax, 10           ; Add 10
        mov [esi], eax        ; Store result
        add esi, 4            ; Next element
        dec ecx
        jnz loop_start
        ret
    
    ; Better approach: Use SIMD instructions
    process_array:
        movdqa xmm0, [array]  ; Load 4 integers at once
        paddd xmm0, [ten_vector] ; Add 10 to each integer
        movdqa [array], xmm0  ; Store results
        ret
    
    section .data
    align 16
    ten_vector dd 10, 10, 10, 10

    Use SIMD (Single Instruction, Multiple Data) instructions like SSE, AVX, or NEON when processing multiple data elements in parallel.

    ; Anti-pattern: Mixing code and data
    section .text
    global _start
    
    _start:
        ; Code...
        jmp after_data
    
    message db "Hello, World!", 0  ; Data in code section
    
    after_data:
        ; More code...
    
    ; Better approach: Proper segmentation
    section .data
    message db "Hello, World!", 0  ; Data in data section
    
    section .text
    global _start
    
    _start:
        ; Code that uses message...

    Use proper segmentation to separate code, data, and uninitialized data. This improves memory management and can help with security features like non-executable data.

    ; Anti-pattern: Unbalanced stack
    process_data:
        push eax
        push ebx
        push ecx
        
        ; Process data...
        
        pop ebx        ; Oops, stack is now unbalanced
        ret            ; Will return to wrong address
    
    ; Better approach: Balanced stack
    process_data:
        push eax
        push ebx
        push ecx
        
        ; Process data...
        
        pop ecx        ; Restore in reverse order
        pop ebx
        pop eax
        ret            ; Stack is balanced

    Maintain proper stack balance. Every push should have a corresponding pop, and they should be in the correct order.

    ; Anti-pattern: Undocumented function
    calculate_checksum:
        xor eax, eax
        mov ecx, [esp+4]
        mov edx, [esp+8]
    loop_start:
        add al, [ecx]
        inc ecx
        dec edx
        jnz loop_start
        ret
    
    ; Better approach: Well-documented function
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ; calculate_checksum - Calculates a simple checksum
    ;
    ; Input:
    ;   [esp+4] - Pointer to data buffer
    ;   [esp+8] - Size of buffer in bytes
    ;
    ; Output:
    ;   eax - 8-bit checksum (sum of all bytes mod 256)
    ;
    ; Destroys: eax, ecx, edx
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    calculate_checksum:
        xor eax, eax          ; Initialize checksum to 0
        mov ecx, [esp+4]      ; Get pointer to buffer
        mov edx, [esp+8]      ; Get buffer size
    loop_start:
        add al, [ecx]         ; Add byte to checksum
        inc ecx               ; Move to next byte
        dec edx               ; Decrement counter
        jnz loop_start        ; Continue if not done
        ret                   ; Return with checksum in eax

    Document your functions thoroughly, including input parameters, output values, and any registers that are modified.

    ; Anti-pattern: No testing infrastructure
    ; Code is written and assembled without testing
    
    ; Better approach: Include test code
    section .text
    global _start
    
    _start:
    %ifdef TESTING
        ; Run tests
        call test_calculate_checksum
        ; More tests...
        
        ; Exit with test result
        mov eax, 1            ; sys_exit
        mov ebx, [test_failures] ; Exit code = number of failures
        int 0x80
    %else
        ; Normal program execution
        ; ...
    %endif
    
    ; Test functions
    test_calculate_checksum:
        push ebp
        mov ebp, esp
        
        ; Test case 1: Empty buffer
        push dword 0          ; Size
        push test_buffer      ; Buffer
        call calculate_checksum
        add esp, 8            ; Clean up stack
        
        cmp eax, 0
        jne test_failure
        
        ; Test case 2: Known values
        ; ...
        
        pop ebp
        ret
        
    test_failure:
        inc dword [test_failures]
        ret
        
    section .data
    test_buffer db 1, 2, 3, 4, 5
    test_failures dd 0

    Include testing infrastructure in your assembly code. This helps catch bugs early and ensures your code works as expected.

    ; Anti-pattern: No version information
    section .text
    global _start
    
    _start:
        ; Program code...
    
    ; Better approach: Include version information
    section .data
    version_info db "MyProgram v1.2.3", 0
    build_date db __DATE__, 0
    build_time db __TIME__, 0
    
    section .text
    global _start
    
    _start:
        ; Program code...

    Include version information in your code and use a version control system like Git. This helps track changes and manage different versions of your code.

    PascalBash
    websitexgithublinkedin
    Powered by Mintlify
    Assistant
    Responses are generated using AI and may contain mistakes.