Примеры Ассемблера

Основные примеры программирования на Ассемблере для низкоуровнего программирования и архитектуры компьютера

💻 Ассемблер Hello World assembly

🟢 simple ⭐⭐⭐⭐

Базовая программа Hello World на ассемблере и базовые концепции машинного языка

⏱️ 25 min 🏷️ assembly, low-level, x86, system programming, machine code
Prerequisites: Computer architecture basics, Understanding of CPU architecture, Memory management
; Assembly Hello World Examples
; These examples use x86-64 assembly syntax (NASM)
; Target: 64-bit Linux/macOS/Windows

section .data
    hello_msg db "Hello, World!", 0
    greeting_msg db "Welcome to Assembly Programming", 0
    name_msg db "Your name: ", 0
    buffer db 256 dup(0)

section .bss
    input_buffer resb 256

section .text
    global _start

_start:
    ; === Basic Hello World ===
    mov rax, 1                  ; system call number for write
    mov rdi, 1                  ; file descriptor 1 (stdout)
    lea rsi, [rel hello_msg]     ; address of message
    mov rdx, hello_msg_len       ; length of message
    syscall                       ; make system call

    ; === Hello World with Variable ===
    mov rax, 1
    mov rdi, 1
    lea rsi, [rel greeting_msg]
    mov rdx, greeting_msg_len
    syscall

    ; === Input Simulation ===
    mov rax, 1
    mov rdi, 1
    lea rsi, [rel name_msg]
    mov rdx, name_msg_len
    syscall

    ; Read input (commented out as this is interactive)
    ; mov rax, 0                  ; system call for read
    ; mov rdi, 0                  ; file descriptor 0 (stdin)
    ; lea rsi, [rel input_buffer] ; buffer
    ; mov rdx, 255                ; max bytes to read
    ; syscall

    ; Exit program
    mov rax, 60                 ; system call for exit
    xor rdi, rdi                 ; exit code 0
    syscall

    ; === Function Example ===
print_message:
    push rbp                    ; save base pointer
    mov rbp, rsp                ; set new base pointer

    mov rax, 1                  ; system call for write
    mov rdi, 1                  ; stdout
    mov rsi, rdi                ; message from stack
    mov rdx, 8                  ; 8 bytes (64-bit pointer)
    syscall                       ; write message

    pop rbp                     ; restore base pointer
    ret                         ; return

section .data
    hello_msg db "Hello, World!", 10
    greeting_msg db "Welcome to Assembly Programming", 35
    name_msg db "Your name: ", 12
    name_msg_len equ $ - name_msg
    hello_msg_len equ $ - hello_msg
    greeting_msg_len equ $ - greeting_msg

section .bss
    input_buffer resb 256

% Alternative Hello World with registers only
section .text
    global _start_registers

_start_registers:
    ; Create message directly in registers
    mov r10, 0x574F4C6C           ; W
    mov r11, 0x6F7266C6           ; o
    mov r12, 0x726C64C2           ; r
    mov r13, 0x6C20646C           ; l
    mov r14, 0x20644D20           ;

; --- Data Definitions ---
section .data
    hello_msg_data db "Hello, World!", 10
    multiline_msg db "Line 1", 10, 13, 10
                db "Line 2", 10, 13, 10
                db "Line 3", 10
    newline db 10
    goodbye_msg db "Goodbye!", 0

    numbers dq 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
    text db "Assembly programming", 0

section .bss
    input_buffer2 resb 256
    result_buffer resb 100
    counter resq 4

; --- Registers and Memory Operations ---
section .text
    global _start_registers

_start_registers:
    ; Initialize registers
    xor rax, rax              ; Clear RAX
    mov rbx, 42               ; RBX = 42
    mov rcx, 100              ; RCX = 100
    mov rdx, 3.14             ; RDX = 3.14 (floating point)

    ; Memory operations
    mov [counter], 0           ; Store 0 at counter address
    mov rbx, [counter]          ; Load from counter to RBX
    inc rbx                   ; RBX = RBX + 1
    mov [counter], rbx          ; Store back to memory

    ; --- Stack Operations ---
    push rax                   ; Save RAX on stack
    push rbx                   ; Save RBX on stack
    push rcx                   ; Save RCX on stack

    pop rcx                    ; Restore RCX from stack
    pop rbx                    ; Restore RBX from stack
    pop rax                    ; Restore RAX from stack

    ; --- Conditional Logic ---
    cmp rbx, 42                ; Compare RBX with 42
    je equal_to_42              ; Jump if equal

    not_equal_to_42:
        mov rax, 1              ; Return 1
        jmp done

    equal_to_42:
        mov rax, 0              ; Return 0

    done:
    ; Exit with status in RAX
    mov rdi, rax              ; Exit code from RAX
    mov rax, 60              ; System call for exit
    syscall

; --- Basic Arithmetic Operations ---
section .text
    global _start_arithmetic

_start_arithmetic:
    ; Addition
    mov rax, 10
    add rax, 5              ; RAX = 10 + 5 = 15
    call print_number        ; Print 15

    ; Subtraction
    mov rax, 20
    sub rax, 8              ; RAX = 20 - 8 = 12
    call print_number        ; Print 12

    ; Multiplication
    mov rax, 6
    imul rax, 7             ; RAX = 6 * 7 = 42
    call print_number        ; Print 42

    ; Division
    mov rax, 50
    mov rdx, 4
    xor rcx, rcx              ; Clear RCX for unsigned division
    idiv rdx                  ; RAX = RAX / RDX, RDX = remainder
    ; RAX = 12, RDX = 2
    call print_number        ; Print quotient
    mov rax, rdx              ; Move remainder to RAX
    call print_number        ; Print remainder

    jmp end_program

; --- Control Flow Examples ---
section .text
    global _start_control_flow

_start_control_flow:
    ; If-else-if structure (using jumps)
    mov rbx, 25              ; Age = 25

    cmp rbx, 18
    jl minor                ; Jump if less than
    je adult
    jge major

    minor:
        call print_minor
        jmp end_if

    adult:
    cmp rbx, 65
    jle senior
    jmp adult_65_or_younger

    major:
    call print_adult
    jmp end_if

    senior:
    call print_senior

    end_if:
    ; Switch-like structure (using jump table)
    mov rcx, 3              ; Day = 3

    cmp rcx, 1
    je print_monday
    cmp rcx, 2
    je print_tuesday
    cmp rcx, 3
    je print_wednesday
    cmp rcx, 4
    je print_thursday
    cmp rcx, 5
    je print_friday
    jmp print_weekend

print_monday:
    call print_monday_func
    jmp end_switch

print_tuesday:
    call print_tuesday_func
    jmp end_switch

print_wednesday:
    call print_wednesday_func
    jmp end_switch

print_thursday:
    call print_thursday_func
    jmp end_switch

print_friday:
    call print_friday_func
    jmp end_switch

print_weekend:
    call print_weekend_func

end_switch:
    jmp loop_example

loop_example:
    ; For loop example (countdown)
    mov rcx, 5              ; Counter = 5

countdown_loop:
    call print_counter
    dec rcx                  ; Decrement counter
    test rcx, rcx            ; Test if zero
    jnz countdown_loop        ; Continue if not zero

    ; While loop example
    mov rbx, 0              ; Counter = 0

while_loop:
    cmp rbx, 3              ; Compare with 3
    jge end_while           ; Exit if >= 3

    call print_counter
    inc rbx                  ; Increment counter
    jmp while_loop

end_while:
    jmp end_program

; --- Loops and Iteration ---
section .text

print_counter:
    push rax                  ; Save registers
    push rdx
    push rcx

    ; Convert number to string (simplified)
    lea rdi, [rel buffer]
    mov r10, rcx              ; Copy counter to R10
    call int_to_ascii       ; Convert to ASCII
    mov byte [rdi], 0        ; Null terminator
    call print_string

    pop rcx                   ; Restore registers
    pop rdx
    pop rax
    ret

; --- String Operations ---
section .text

print_string:
    push rax                  ; Save registers
    push rdi
    push rdx

    ; Calculate string length
    mov rax, rdi              ; String address
    xor rcx, rcx              ; RCX = 0
    mov rdx, rdi              ; Start address

find_end:
    cmp byte [rdx], 0        ; Check for null terminator
    je end_found            ; Found end if null
    inc rcx                  ; Increment count
    inc rdx                  ; Move to next byte
    jmp find_end           ; Continue searching

end_found:
    ; Print string (system call)
    mov rax, 1              ; write syscall
    mov rdi, 1              ; stdout
    lea rsi, [rel buffer]     ; String address
    mov rdx, rcx              ; String length
    syscall

    pop rdx                   ; Restore registers
    pop rdi
    pop rax
    ret

; Simple ASCII to integer conversion
int_to_ascii:
    ; Input: number in RCX, output buffer in RDI
    mov rax, rcx              ; Copy number to RAX
    mov rbx, 10              ; Divisor

convert_loop:
    test rax, rax            ; Check if zero
    je done_converting

    xor rdx, rdx              ; Clear RDX
    div rbx                  ; Divide by 10
    add rdx, '0'             ; Add ASCII '0' (48)
    push rdx                  ; Save digit
    jmp convert_loop

done_converting:
    ; Pop digits and build string
    mov rbx, rdi              ; Buffer position
    pop rcx                  ; Digit
    mov byte [rbx], cl          ; Store digit

    test rcx, rcx              ; Check if more digits
    jne more_digits
    mov byte [rbx], 0        ; Null terminator

    ret

more_digits:
    inc rbx                  ; Move buffer position
    jmp done_converting

print_number:
    push rax                  ; Save registers
    push rdi
    push rdx
    push rcx

    ; Convert RAX to ASCII
    lea rdi, [rel buffer]
    mov r10, rax              ; Copy number to R10
    call int_to_ascii       ; Convert to ASCII
    mov byte [rdi], 0        ; Null terminator
    call print_string

    pop rcx                   ; Restore registers
    pop rdx
    pop rdi
    pop rax
    ret

print_minor:
    mov rax, 1
    call print_message
    ret

print_adult:
    mov rax, 2
    call print_message
    ret

print_senior:
    mov rax, 3
    call print_message
    ret

print_monday_func:
    mov rax, 4
    call print_message
    ret

print_tuesday_func:
    mov rax, 5
    call print_message
    ret

print_wednesday_func:
    mov rax, 6
    call print_message
    ret

print_thursday_func:
    mov rax, 7
    call print_message
    ret

print_friday_func:
    mov rax, 8
    call print_message
    ret

print_weekend_func:
    mov rax, 9
    call print_message
    ret

; --- Memory and Pointers ---
section .text
global _start_memory

_start_memory:
    ; Allocate memory on stack
    sub rsp, 32              ; Allocate 32 bytes

    ; Store values in memory
    mov dword [rsp], 0x12345678    ; Little endian: 0x78563412
    mov dword [rsp + 4], 0x9abcdef0   ; Little endian: 0xf0cde9ba
    mov dword [rsp + 8], 0x13579ace   ; Little endian: 0xce9a5713

    ; Load and display
    mov eax, [rsp]
    call print_hex        ; Print first 32-bit value

    mov eax, [rsp + 8]
    call print_hex        ; Print second 32-bit value

    ; Restore stack
    add rsp, 32
    jmp end_program

print_hex:
    push rax                  ; Save registers
    push rcx
    push rdx
    push rsi
    push rdi
    push r8
    push r9
    push r10
    push r11

    ; Print in hex format
    lea rsi, [rel buffer]    ; Buffer address
    mov rdi, 0              ; No flags
    mov rax, rax              ; Value to print
    call print_hex_with_prefix

    pop r11
    pop r10
    pop r9
    pop r8
    pop rdi
    pop rsi
    pop rdx
    pop rcx
    pop rax
    ret

print_hex_with_prefix:
    ; RAX: value, RDI: flags, RSI: buffer address
    push rax                  ; Save registers
    push rbx
    push rcx
    push rdx
    push rsi
    push rdi

    ; Add prefix
    mov byte [rsi], '0'
    mov byte [rsi + 1], 'x'

    ; Convert to hex string
    mov rbx, rax              ; Copy value to RBX
    shr rbx, 32               ; Get high byte
    and rbx, 0xFF           ; Keep only low byte
    call byte_to_hex
    mov [rsi + 2], bl

    mov rbx, rax              ; Restore value
    and rbx, 0xFF           ; Get low byte
    call byte_to_hex
    mov [rsi + 3], bl

    mov byte [rsi + 4], ' '
    shr rax, 48               ; Get high 16 bits
    and rax, 0xFFFF           ; Keep only 16 bits
    shr rax, 8
    call byte_to_hex
    mov [rsi + 5], bl

    mov rbx, rax              ; Restore 16 bits
    and rbx, 0xFF
    call byte_to_hex
    mov [rsi + 6], bl

    shr rax, 8
    and rbx, 0xFF
    call byte_to_hex
    mov [rsi + 7], bl

    and rax, 0xFF
    call byte_to_hex
    mov [rsi + 8], bl

    mov byte [rsi + 9], 0   ; Null terminator
    call print_string

    pop rdi
    pop rsi
    pop rdx
    pop rcx
    pop rbx
    pop rax
    ret

byte_to_hex:
    ; Input: RBX = byte value (0-15), output: BL = ASCII hex character
    cmp rbx, 10
    jl less_than_10
    cmp rbx, 15
    jg greater_than_15

between_10_15:
    add rbx, 'A' - 10    ; Convert to A-F
    jmp done_hex

less_than_10:
    add rbx, '0'           ; Convert to 0-9
    jmp done_hex

greater_than_15:
    mov bl, '?'           ; Invalid byte
    jmp done_hex

done_hex:
    ret

; --- System Calls and OS Interaction ---
section .text
global _start_system

_start_system:
    ; Get current time
    mov rax, 201              ; sys_gettimeofday
    xor rdi, rdi              ; Clear RDI (struct pointer)
    lea rsi, [rel time_struct]
    xor rdx, rdx              ; Clear RDX (timezone pointer)
    syscall

    ; Extract seconds from time struct (64-bit)
    mov rbx, [rsi]          ; Get seconds value

    ; Print current time (simplified)
    lea rsi, [rel buffer]
    mov rdi, 1              ; stdout
    mov rdx, 50              ; Max length
    call format_time_string

    mov rax, 1
    syscall

    ; Get process ID
    mov rax, 39              ; sys_getpid
    syscall

    mov rbx, rax              ; Process ID
    lea rsi, [rel buffer]
    mov rdi, 1
    mov rdx, 20
    call format_process_id

    mov rax, 1
    syscall

    ; File operations (create file)
    mov rax, 2              ; sys_open
    lea rdi, [rel filename]
    mov rsi, 0x41            ; O_WRONLY | O_CREAT
    mov rdx, 0o600            ; rw-rw-rw-
    mov r10, 0o664            ; rw-rw-rw-
    syscall

    ; Save file descriptor
    mov r14, rax              ; Save file descriptor

    ; Write to file
    mov rax, 1              ; sys_write
    mov rdi, r14              ; File descriptor
    lea rsi, [rel file_content]
    mov rdx, file_content_len
    syscall

    ; Close file
    mov rax, 3              ; sys_close
    mov rdi, r14              ; File descriptor
    syscall

    jmp end_program

; --- Helper Functions ---
section .data
    filename db "assembly_output.txt", 0
    file_content db "This is written from assembly!", 32
    file_content_len equ $ - file_content

format_string:
    db "Current time: %ld seconds", 0

format_process_id:
    db "Process ID: %d", 0

buffer: 256

time_struct:
    .tv_sec dq 0          ; seconds since epoch
    .tv_usec dq 0         ; microseconds

section .bss
    time_struct: resb sizeof(time_struct)

; --- String Constants ---
section .data
    print_minor: db "You are a minor (under 18)", 0
    print_adult: db "You are an adult (18-64)", 0
    print_senior: db "You are a senior (65+)", 0

    print_monday: db "Monday", 0
    print_tuesday: db "Tuesday", 0
    print_wednesday: db "Wednesday", 0
    print_thursday: db "Thursday", 0
    print_friday: db "Friday", 0
    print_weekend: db "Weekend", 0

    hello_data:
    .long 0x6F726C6C6F20456C6C6F20
    .long 0x4F2064C6C692C656E
    .quad 0x50726578696C6C6F
    .quad 0x676F672A6D69736

    greeting_data:
    .long 0x57656C65736574206969
    .long 0x73206C6F67267616D
    .quad 0x726F726F676D72696E
    .quad 0x676C6F676D6C6B20

    name_data:
    .long 0x59686F6C620656C64
    .long 0x7320C3F972064656E
    .quad 0x6F75726965736C6C64

section .bss
    input_buffer: resb 256
    result_buffer: resb 256

    ; Length calculations
    hello_msg_len equ $ - hello_msg
    greeting_msg_len equ $ - greeting_msg
    name_msg_len equ $ - name_msg

; --- Program Exit ---
end_program:
    mov rax, 60             ; sys_exit
    xor rdi, rdi             ; Exit code 0
    syscall

💻 Управление памятью в Ассемблере assembly

🟡 intermediate ⭐⭐⭐⭐⭐

Расширенные операции с памятью и управление указателями в ассемблере

⏱️ 40 min 🏷️ assembly, x86, low-level, system programming
Prerequisites: Computer architecture fundamentals, Assembly language basics, System call knowledge, Memory management
; Assembly Memory Management Examples
; x86-64 assembly (NASM syntax)
; Shows stack allocation, heap allocation, and pointer operations

section .data
    prompt db "Enter a number: ", 0
    result_msg db "Result: %d", 0
    newline db 10

section .bss
    heap_buffer resb 4096    ; 4KB heap

section .text
    global _start

_start:
    ; Initialize stack frame
    push rbp                ; Save base pointer
    mov rbp, rsp            ; Set new base pointer

    ; === Stack Allocation ===
    sub rsp, 32              ; Allocate 32 bytes on stack
    mov dword [rsp], 100     ; Store first integer
    mov dword [rsp + 4], 200  ; Store second integer
    mov dword [rsp + 8], 300  ; Store third integer
    mov dword [rsp + 12], 400 ; Store fourth integer

    ; Display stack values
    call print_stack_values

    ; === Heap Allocation ===
    ; Request memory from operating system
    mov rax, 12              ; mmap system call
    mov rdi, 0              ; addr = NULL (let OS choose)
    mov rsi, 4096           ; size = 4KB
    mov rdx, 3              ; PROT_READ | PROT_WRITE
    mov r10, 0x22            ; MAP_PRIVATE | MAP_ANONYMOUS
    xor r8, r8              ; No flags
    syscall

    ; Check if allocation succeeded
    test rax, rax
    js allocation_failed    ; Jump if allocation failed
    mov r15, rax              ; Save heap pointer

    ; Write to heap
    mov dword [r15], 1000    ; Store value
    mov dword [r15 + 4], 2000 ; Store value
    mov dword [r15 + 8], 3000 ; Store value

    ; Display heap values
    call print_heap_values

    ; === Pointer Operations ===
    mov r12, r15              ; R12 = heap pointer
    mov r13, [r12]         ; R13 = *R12

    ; Pointer arithmetic
    add r13, 8              ; R13 = R13 + 8
    mov [r12 + 8], 4000     ; *(R12 + 8) = 4000

    ; Display updated heap values
    call print_updated_heap

    ; Pointer offset calculation
    mov r13, r15              ; R13 = heap pointer
    lea r14, [r13 + 16]    ; R14 = R13 + 16
    mov [r14], 5000     ; Store value at R14
    mov dword [r14 + 4], 6000 ; Store value at R14 + 4

    ; Display offset example
    call print_offset_example

    ; === Dynamic Memory Reallocation ===
    ; Free current allocation
    mov rax, 11              ; munmap system call
    mov rdi, r15              ; address to free
    mov rsi, 4096           ; size to free
    syscall

    ; Reallocate larger memory
    mov rax, 12              ; mmap system call
    mov rdi, 0              ; NULL
    mov rsi, 8192           ; 8KB
    mov rdx, 3              ; PROT_READ | PROT_WRITE
    mov r10, 0x22            ; MAP_PRIVATE | MAP_ANONYMOUS
    xor r8, r8              ; No flags
    syscall

    test rax, rax
    js allocation_failed
    mov r15, rax              ; New heap pointer

    ; Copy data from temporary storage
    mov rsi, rsp              ; Use stack as temporary storage
    mov dword [rsi], 1000   ; First value
    mov dword [rsi + 4], 2000 ; Second value
    mov dword [rsi + 8], 3000 ; Third value
    mov rdx, 12              ; 3 values to copy

    rep movsq
    copy data from RSI to [R15]
    mov rdi, r15              ; Destination (heap)
    mov rsi, rsp              ; Source (stack)
    syscall

    ; Display reallocated heap
    call print_reallocated_heap

    ; === Array Operations ===
    ; Allocate array on heap
    mov rax, 12              ; mmap system call
    mov rdi, 0
    mov rsi, 80              ; 20 integers * 4 bytes = 80 bytes
    mov rdx, 3              ; PROT_READ | PROT_WRITE
    mov r10, 0x22            ; MAP_PRIVATE | MAP_ANONYMOUS
    xor r8, r8
    syscall

    test rax, rax
    js allocation_failed
    mov r14, rax              ; Array pointer

    ; Fill array with values
    mov rdi, 0              ; Index = 0
    mov r10, 20              ; Array length

array_fill_loop:
    mov dword [r14 + rdi*4], rdi  ; array[index] = index
    inc rdi                  ; increment index
    cmp rdi, r10              ; Compare with array length
    jl array_fill_loop        ; Continue if index < length

    ; Display array
    call print_array

    ; === Memory Cleanup ===
    free_heap:
        ; Free array
        mov rax, 11              ; munmap
        mov rdi, r14              ; address
        mov rsi, 80              ; size
        syscall

        ; Free heap
        mov rax, 11              ; munmap
        mov rdi, r15              ; address
        mov rsi, 4096           ; size
        syscall

    free_stack:
        ; Restore stack
        add rsp, 32              ; Deallocate stack memory
        pop rbp                ; Restore base pointer

    ; Exit program
    mov rax, 60
    xor rdi, rdi
        syscall

allocation_failed:
    call print_error
    mov rax, 60
    mov rdi, 1              ; Exit code 1 (error)
        syscall

; --- Helper Functions ---

print_stack_values:
    push rax                  ; Save registers
    push rdi
    push rsi
    push rdx

    lea rsi, [rel stack_msg]
    mov rax, 1
    mov rdi, 1
    syscall

    ; Print values
    lea rdi, [rel stack_msg]
    mov eax, [rsp]           ; First value
    call print_int
    lea rdi, [rel second_msg]
    mov eax, [rsp + 4]     ; Second value
    call print_int
    lea rdi, [rel third_msg]
    mov eax, [rsp + 8]     ; Third value
    call print_int
    lea rdi, [rel fourth_msg]
    mov eax, [rsp + 12]    ; Fourth value
    print_int:
        push rax              ; Save number
        lea rsi, [rel format_buffer]
        mov rdx, 20
        call format_int
        mov rax, 1
        mov rdi, 1
        syscall
        pop rax              ; Restore number
        jmp print_string

    pop rdx
    pop rsi
    pop rdi
    pop rax
    ret

print_heap_values:
    push rax
    push rdi
    push rsi
    push rdx

    lea rsi, [rel heap_msg]
    mov rax, 1
    mov rdi, 1
    syscall

    mov eax, [r15]           ; First value
    call print_int
    mov eax, [r15 + 4]       ; Second value
    call print_int
    mov eax, [r15 + 8]       ; Third value
    call print_int

    pop rdx
    pop rsi
    pop rdi
    pop rax
    ret

print_updated_heap:
    push rax
    push rdi
    push rsi
    push rdx

    lea rsi, [rel updated_msg]
    mov rax, 1
    mov rdi, 1
    syscall

    ; Display original values
    mov eax, [r12]         ; *R12 (was 1000)
    call print_int
    mov eax, [r12 + 8]     ; *(R12 + 8) (was 2000)
    call print_int

    ; Display updated values
    lea rdi, [rel updated_value_msg]
    mov eax, [r12]         ; *R12 (now 1000)
    call print_int
    lea rdi, [rel updated_at_msg]
    mov eax, [r12 + 8]     ; *(R12 + 8) (now 4000)
    call print_int

    lea rdi, [rlf_separator]
    mov rax, 1
    mov rdi, 1
    syscall

    pop rdx
    pop rsi
    pop rdi
    pop rax
    ret

print_offset_example:
    push rax
    push rdi
    push rsi
    push rdx

    lea rsi, [rel offset_msg]
    mov rax, 1
    mov rdi, 1
    syscall

    lea rdi, [rel base_pointer_msg]
    mov rbx, r12             ; Base pointer
    call print_hex
    lea rsi, [rlf_separator]
    mov rax, 1
    syscall

    lea rdi, [rel offset_value_msg]
    mov r13, [r13]         ; R13 = R12 + 16
    call print_hex
    lea rsi, [rlf_separator]
    mov rax, 1
    syscall

    lea rdi, [rlf_separator]
    mov rax, 1
    syscall

    pop rdx
    pop rsi
    pop rdi
    pop rax
    ret

print_reallocated_heap:
    push rax
    push rdi
    push rsi
    push rdx

    lea rsi, [rel reallocated_msg]
    mov rax, 1
    mov rdi, 1
    syscall

    ; Display all values
    lea rdi, [rlf_separator]
    mov eax, [r15]         ; First value
    call print_int
    lea rdi, [rlf_separator]
    mov eax, [r15 + 4]     ; Second value
    call print_int
    lea rdi, [r15 + 8]     ; Third value
    call print_int

    lea rsi, [rlf_separator]
    mov rax, 1
    syscall

    pop rdx
    pop rsi
    pop rdi
    pop rax
    ret

print_array:
    push rax
    push rdi
    push rsi
    push rdx

    lea rsi, [rel array_msg]
    mov rax, 1
    mov rdi, 1
    syscall

    lea rdi, [rlf_separator]
    mov r10, 0              ; Index = 0
array_print_loop:
    cmp r10, 20              ; Compare with array length
    jge array_done           ; Exit if done

    lea rdi, [rlf_format_int]
    mov rdi, 1
    mov eax, [r14 + r10*4]  ; array[index]
    call print_int
    lea rdi, [rlf_separator]
    mov rax, 1
    syscall

    inc r10                  ; Increment index
    jmp array_print_loop

array_done:
    pop rdx
    pop rsi
    pop rdi
    pop rax
    ret

print_int:
    ; Input: EAX = integer, RDI = buffer, RDX = max length
    ; Output: integer in RAX
    ; Note: Simplified - doesn't handle negatives or large numbers
    push rax
    push rdi
    push rsi

    lea rsi, [rdi]         ; String buffer address
    mov r8, rax              ; Copy number
    xor rbx, rbx              ; Clear RBX (no negative handling)
    add r8, '0'              ; Convert to ASCII

    ; Determine number of digits
    cmp r8, 10              ; Less than 10
    jl single_digit

    ; Two or more digits
    mov r9, 10
    digit_loop:
        xor rdx, rdx              ; Clear RDX for division
        xor r10, r10              ; Clear R10 for remainder
        div rbx, r9              ; Divide by 10
        add r11, '0'             ; ASCII '0'
        add r11, r10             ; Add remainder ASCII
        mov [rsi], r11         ; Store digit character
        inc rsi                  ; Move buffer position
        cmp r8, 10              ; Check if more digits
    jge digit_loop

    single_digit:
        add r11, '0'             ; ASCII '0'
        mov [rsi], r11         ; Single digit

    ; Terminate string
    mov byte [rsi], 0        ; Null terminator

    mov byte [rsi], 10       ; Newline
    mov byte [rsi + 1], 0     ; Newline

    pop rsi
    pop rdi
    pop rax
    ret

print_error:
    push rax
    push rdi
    push rsi

    lea rsi, [rel error_msg]
    mov rax, 1
    mov rdi, 2              ; stderr
    syscall

    pop rsi
    pop rdi
    pop rax
    ret

; --- String Constants ---
section .data
    stack_msg db "Stack values:", 0
    second_msg db "Value 1: ", 0
    third_msg db "Value 2: ", 0
    fourth_msg db "Value 3: ", 0

    heap_msg db "Heap values:", 0
    updated_msg db "Original: [1000, 2000], Updated: [1000, 4000]", 0
    updated_value_msg db "Updated at offset 16: 4000", 0

    base_pointer_msg db "Base pointer: ", 0
    offset_value_msg db "Value at R12+16: ", 0

    array_msg db "Array contents:", 0
    offset_msg db "Offset example pointer arithmetic:", 0

    reallocated_msg db "Reallocated heap (8KB) contents:", 0

    error_msg db "Error: Memory allocation failed!", 0
    format_buffer: db "%d"

    format_int: db "%d", 0
    format_hex: db "0x%016x", 0

    buffer: 256

rlf_separator db "--------------------", 10
    newline db 10

section .bss
    ; Variables
    input_buffer: resb 256
    result_buffer: resb 256

; Length calculations
    greeting_msg_len equ $ - greeting_msg
    hello_msg_len equ $ - hello_msg
    name_msg_len equ $ - name_msg

    ; Memory allocation sizes
    stack_size equ 32          ; 4 integers on stack
    heap_size equ 4096         ; 4KB on heap
    array_size equ 80           ; 20 integers (20 * 4 bytes)
    large_heap_size equ 8192      ; 8KB for reallocation

end_program:
    jmp _start_memory

; --- Static Data Examples ---
section .data
    static_int: dd 12345678
    static_float: dd 3.14159
    static_string: db "Hello from .data section", 0
    static_array: dd 1, 2, 3, 4, 5
    static_2d_array:
        dw 1, 2, 3, 4
        dw 5, 6, 7, 8

section .text
    global _start_static

_start_static:
    ; Access static data
    mov rax, [rel static_int]
    call print_hex        ; Print static_int as hex
    mov rdx, [rel static_float]
    call print_float

    ; Access static string
    mov rax, 1
    mov rdi, 1              ; stdout
    lea rsi, [rel static_string]
    mov rdx, static_string_len
    syscall

    ; Access static array
    mov rax, [static_array + 8]  ; Access element 2 (0-based index 2 = 3)
    call print_int        ; Should print 3

    ; Access 2D array
    mov rax, [static_2d_array + 8]  ; Access element at [1][0]
    call print_int        ; Should print 5

    ; Exit
    mov rax, 60
    xor rdi, rdi
    syscall

static_int_len equ $ - static_int
static_string_len equ $ - static_string

; --- Data Alignment Examples ---
section .data
    aligned_data align 16
    db "This data is aligned on 16-byte boundary", 0
    unaligned_data db "This data has no alignment constraints", 0

    ; Aligned arrays
    aligned_array1 dd 1.0, 2.0, 3.0
    aligned_array2 dd 4.0, 5.0, 6.0

section .bss
    aligned_buffer resb 1024  ; 1KB aligned on page boundary

section .text
    global _start_aligned

_start_aligned:
    ; Demonstrate alignment
    lea rsi, [rel aligned_data]
    call print_string

    lea rsi, [rel unaligned_data]
    call print_string

    ; Show aligned addresses
    lea rsi, [rel aligned_array1]
    lea rdx, [rel aligned_array1]
    call print_hex_with_prefix
    mov byte [rsi], 10
    lea rsi, [rel aligned_array1 + 8]
    lea rdx, [rel aligned_array1 + 8]
    call print_hex_with_prefix

    mov rax, 60
    xor rdi, rdi
    syscall

    ret

print_hex_with_prefix:
    ; Input: RAX = value, RDI = flags, RSI = buffer
    push rax
    push rdi
    push rsi
    push rdx
    push rcx
    push r11

    ; Print "0x" prefix
    mov byte [rsi], '0'
    mov byte [rsi + 1], 'x'

    ; Convert to hex
    mov rax, rax              ; Value to print
    shr rax, 32               ; Get high byte
    and rbx, 0xFF           ; Keep only low byte
    call byte_to_hex
    mov [rsi + 2], bl

    shr rax, rax              ; Get high 16 bits
    and rax, 0xFFFF           ; Keep only 16 bits
    shr rax, rax              ; Get high byte
    and rbx, 0xFF           ; Keep low byte
    call byte_to_hex
    mov [rsi + 6], bl

    shr rax, rax              ; Get high byte
    and rbx, 0xFF           ; Keep low byte
    call byte_to_hex
    mov [rsi + 10], bl

    mov byte [rsi + 12], ' '
    mov byte [rsi + 13], 0   ; Null terminator
    call print_string

    pop r11
    pop rcx
    pop rdx
    pop rsi
    pop rdi
    pop rax
    ret

print_float:
    ; Print floating point number (simplified)
    ; Input: RDX = double precision float
    push rax
    push rdi
    push rdx

    ; Simple floating point printing (not comprehensive)
    ; This is a very basic implementation
    mov rbx, rdx              ; Move float to RBX
    mov rcx, 0              ; Initialize integer part
    integer_part trunc rbx      ; Extract integer part
    mov rdx, rbx
    sub rdx, integer_part    ; Get fractional part
    rdx = rdx * 10         ; Scale for 1 decimal place

    ; Print integer part
    lea rsi, [rel format_buffer]
    mov rax, integer_part
    call print_int
    lea rsi, [rlf_separator]
    mov rax, 1
    syscall

    ; Print decimal part
    lea rsi, [rlf_separator]
    mov rax, rdx
    call print_int

    pop rdx
    pop rdi
    pop rax
    ret

section .data
    format_float: db "%.1f", 0

rlf_separator db "; ", 10

; --- Type Examples ---
section .data
    char_data: db "A", "B", "C", "D", "E", 0
    word_data: dw 0x41424C42, 0x4F6E69742, 0x727465742, 0x6E6F6C6F
    dword_data: dq 0x123456789ABCDEF000, 0xFEDCBA9876543210
    qword_data: dq 0x0123456789ABCDEF000, 0x89ABCDEF0123456789, 0xFEDCBA9876543210, 0x0ABCDEF0123456789

section .bss
    char_array resb 6
    word_array resw 5
    dword_array resd 2
    qword_array resq 2

section .text
    global _start_types

_start_types:
    ; Character operations
    lea rdi, [rel char_data]
    mov al, [rdi + 1]     ; Get 'B'
    cmp al, 'A'           ; Compare with 'A'
    mov al, 'a'           ; Convert to lowercase if needed

    ; Print all characters
    char_loop:
        cmp al, 0              ; Check for null terminator
        je char_done
        call print_char
        inc rdi              ; Move to next character
        jmp char_loop

char_done:
    lea rsi, [rlf_separator]
    call print_string

    ; Word operations (little-endian)
    mov rsi, [rel word_data]
    mov r10, 0              ; Index 0
    word_loop:
    cmp r10, length(word_data) / 8
    jge word_done

    ; Get word at index r10
    mov rax, [rsi + r10*4]
    call print_hex
    lea rsi, [rlf_separator]
    inc r10
    jmp word_loop

word_done:
    lea rsi, [rlf_separator]
    call print_string

    ; Double word operations
    lea rsi, [rel dword_data]
    mov r10, 0              ; Index 0
    dword_loop:
    cmp r10, length(dword_data) / 8
    jge dword_done

    ; Get dword at index r10
    mov rax, [rsi + r10*8]
    mov rbx, rax              ; Low 32 bits
    shr rdx, 32                ; High 32 bits
    or rax, rbx              ; Combine high and low
    call print_hex
    lea rsi, [rlf_separator]
    inc r10
    jmp dword_loop

dword_done:
    lea rsi, [rlf_separator]
    call print_string

    ; Quad word operations
    lea rsi, [rel qword_data]
    mov r10, 0              ; Index 0
    qword_loop:
    cmp r10, length(qword_data) / 16
    jge qword_done

    ; Get quad word at index r10
    mov rax, [rsi + r10*16]     ; Low 64 bits
    mov rbx, [rsi + r10*16 + 8] ; High 64 bits
    call print_hex
    lea rsi, [rlf_separator]
    inc r10
    jmp qword_loop

qword_done:
    lea rsi, [rlf_separator]
    call print_string

    ; Exit
    mov rax, 60
    xor rdi, rdi
    syscall

print_char:
    push rax
    mov rax, 1
    mov rdi, 1
    mov rsi, rdi
    mov rdx, 1
    syscall
    pop rax
    ret

length:
    $ equ $ - word_data
    length: equ $ - dword_data
    length: equ $ - qword_data

end_program:
    jmp _start_types

; --- System Call Examples ---
section .text
    global _start_syscalls

_start_syscalls:
    ; === File Operations ===
    ; Create file
    mov rax, 2              ; sys_open
    lea rdi, [rel test_file]
    mov rsi, 0o641        ; O_WRONLY | O_CREAT
    mov rdx, 0o644        ; 0o640
    mov r10, 0o666        ; rw-rw-rw-
    syscall

    test rax, rax              ; Check for error
    js file_error

    mov r15, rax              ; Save file descriptor

    ; Write to file
    mov rax, 1              ; sys_write
    mov rdi, r15              ; File descriptor
    lea rsi, [rel file_content]
    mov rdx, file_content_len
    syscall

    ; Close file
    mov rax, 3              ; sys_close
    mov rdi, r15              ; File descriptor
    syscall

    ; === Directory Operations ===
    ; Create directory
    mov rax, 83             ; sys_mkdir
    lea rdi, [rel test_dir]
    mov rsi, 0o755        ; drwxr-xr-x
    syscall

    test rax, rax              ; Check for error
    js dir_error

    ; === Process Operations ===
    ; Fork process
    mov rax, 57             ; sys_fork
    syscall

    test rax, rax              ; Check fork result
    js parent_process

parent_process:
    ; Wait for child process
    mov rax, 61             ; sys_wait4
    xor rdi, rdi              ; No status request
    syscall

    jmp end_syscalls

child_process:
    ; Child process executes here
    mov rax, 60             ; sys_exit
    mov rdi, 0              ; Exit code 0
    syscall

file_error:
    call print_error
    jmp end_syscalls

dir_error:
    call print_error
    jmp end_syscalls

end_syscalls:
    jmp end_program

section .data
    test_file db "test_file.txt", 0
    test_dir db "test_directory", 0
    file_content db "This is test content written from assembly!", 0
    file_content_len equ $ - file_content

; === Constants ===
    O_RDONLY equ 0o000000
    O_WRONLY equ 0o000001
    O_RDWR equ 00000002
    O_CREAT equ 00000100
    O_EXCL equ 00000200
    O_TRUNC equ 00001000
    O_APPEND equ 0000200
    O_DIRECTORY = 00040000
    O_NOFOLLOW = 0100000
    O_SYNC = 0010000

    PROT_READ equ 0x1
    PROT_WRITE equ 0x2
    PROT_EXEC = 0x4

    MAP_PRIVATE equ 0x02
    MAP_ANONYMOUS equ 0x20
    MAP_SHARED equ 0x01
    MAP_DENYWRITE 0x100

    STDIN_FILENO equ 0
    STDOUT_FILENO equ 1
    STDERR_FILENO equ 2

    --- Environment Variables ---
section .data
    envp_home db "/home/user", 0
    envp_path db "/usr/bin:/bin", 0
    envp_lang db "en_US.UTF-8", 0

section .bss
    env_vars resb 64

    ; String length calculations
    file_content_len equ $ - file_content
    test_file_len equ $ - test_file
    test_dir_len equ $ - test_dir

    ; === Debugging Examples ===
section .text
    global _start_debug

_start_debug:
    ; Enable debugging output
    pushfq  ; Clear all flags

    ; Print register states
    call print_registers

    ; Stack manipulation example
    push r15
    push r14
    push r13
    push r12
    push r11
    push r10
    push r9
    push r8
    push rdx
    push rcx
    push rbx
    push rax

    ; Display initial stack state
    call print_stack_frame

    ; Modify stack
    pop rax
    mov rax, 999
    push rax
    inc qword ptr [rsp]    ; Access through modified pointer

    ; Display modified stack state
    call print_stack_frame

    ; Restore all registers
    pop rax
    pop rbx
    pop rcx
    pop rdx
    pop r9
    pop r10
    pop r11
    pop r12
    pop r13
    pop r14
    pop r15

    ; Exit with status 0
    mov rax, 60
    xor rdi, rdi
    syscall

; --- Utility Functions ---

print_registers:
    ; Print all general-purpose registers
    push rax
    push rdi
    push rsi
    push rdx

    ; General purpose registers
    lea rdi, [rl register_msg]
    mov rax, r15          ; R15
    mov rbx, r14          ; R14
    rcx, r13           ; RCX
    rdx, r12           ; RDX
    rsi, r11           ; R11
    r10, r10           ; R10
    r9, r9              ; R9
    r8, r8              ; R8

    call print_hex_with_prefix
    lea rsi, [rlf_separator]
    mov rax, r13           ; RCX
    lea rdx, [rlf_separator]
    mov rbx, r14           ; RBX
    call print_hex_with_prefix
    lea rdi, [rlf_separator]
    mov rax, r15           ; R15
    lea rdx, [rlf_separator]
    mov rbx, r12           ; RDX
    call print_hex_with_prefix

    ; Special purpose registers
    lea rdi, [rlf_sep2]
    mov rdi, [rlf_rip]
    call print_hex_with_prefix
    lea rdi, [rlf_separator]
    mov rdi, [rlf_rsp]
    call print_hex_with_prefix

    lea rdi, [rlf_separator]
    mov rdi, [rlf_flags]
    mov rax, rflags           ; RFLAGS register
    call print_hex_with_prefix

    lea rdi, [rlf_separator]
    mov rdi, [rlf_instruction_pointer]
    mov rax, [rip]             ; Instruction pointer
    call print_hex_with_prefix

    pop rdx
    pop rsi
    pop rax
    ret

print_stack_frame:
    ; Print stack frame information
    push rax
    push rdi
    push rsi
    push rdx

    lea rdi, [rl stack_msg]
    mov rbp, [rsp]           ; Get current base pointer

    lea rsi, [rl rbp_msg]
    mov rax, rbp
    call print_hex_with_prefix

    lea rdi, [rlf_separator]
    lea rdi, [rl rsp_msg]
    mov rax, rsp             ; Current stack pointer
    sub rax, rbp             ; Calculate size of frame
    call print_hex_with_prefix

    lea rdi, [rl_frame_end_msg]
    call print_string

    pop rdx
    pop rsi
    pop rax
    ret

print_hex_with_prefix:
    ; Input: RAX = value, RDI = flags, RSI = buffer, RDX = max length
    push rax
    push rdi
    push rsi
    push rdx
    push rcx

    add rsp, 32              ; Adjust for saves

    ; Determine value range and use appropriate format
    cmp rax, -2147483648       ; Most negative 32-bit int
    jl signed_32
    cmp rax, 2147483647        ; Most positive 32-bit int
    jle signed_32

signed_32:
    mov rdx, 11             ; Max digits for 32-bit signed int
    lea rsi, [rl format_int32]
    mov rcx, rax              ; Number to ASCII
    jmp print_number_core

unsigned_32:
    mov rdx, 10             ; Max digits for 32-bit unsigned int
    lea rsi, [rel format_uint32]
    mov rcx, rax              ; Number to ASCII
    jmp print_number_core

print_number_core:
    ; Print number using standard formatting
    ; RAX = number, RDI = flags, RSI = buffer, RDX = max length, RCX = number
    ; RBX is modified by print_number_core to return

    mov rdx, rax              ; Number
    lea rsi, [rsi]           ; Buffer address

    digit_loop:
    xor rcx, rcx              ; Clear RCX
    mov rax, rdx              ; Move number back
    div rcx, 10             ; Extract last digit
    add rbx, '0'             ; Convert to ASCII
    mov [rsi], rbx
    inc rsi                   ; Increment buffer position
    cmp rcx, 0
    jne digit_loop

    mov byte [rsi], 0       ; Null terminator
    call print_string
    add rsp, 32              ; Restore stack
    pop rcx
    pop rdx
    pop rdi
    pop rax
    ret

print_stack_msg: db "Stack frame:", 0
rlf_separator: db "--------------------", 10
rlf_rsp: db "RSP:", 0
rlf_rbp: db "RBP:", 0
rlf_instruction_pointer: db "RIP:", 0
rlf_flags: db "RFLAGS:", 0
rlf_frame_end_msg: db "End of frame", 0

rlf_separator: db "; ", 10
rlf_sep2: db "; ", 10

format_int32: db "%d", 0
format_uint32: db "%u", 0

register_msg: db "General Purpose:", 0
rlf_rip: db "RIP:", 0
rlf_rsp: db "RSP:", 0
rlf_flags: db "RFLAGS:", 0
rlf_instruction_pointer: db "RIP:", 0

format_hex: db "0x%016lx", 0

section .bss
    input_buffer resb 256
    result_buffer resb 256

    ; Constants
    STDIN_FILENO equ 0
    STDOUT_FILENO equ 1
    STDERR_FILENO equ 2

    ; Length calculations
    greeting_msg_len equ $ - greeting_data
    hello_data_len equ $ - hello_data
    name_msg_len equ $ - name_data

print_error:
    push rax
    push rdi
    push rsi

    lea rsi, [rel error_msg]
    mov rax, 1
    mov rdi, 2              ; stderr
    syscall

    pop rsi
    pop rdi
    pop rax
    ret

; --- Memory Management Examples ---
section .text
    global _start_memory_management

_start_memory_management:
    ; Initialize stack
    push rbp
    mov rbp, rsp

    ; Allocate different sized memory blocks
    mov rdi, 0x1000        ; 4KB
    mov rsi, 0x2000        ; 8KB
    mov rdx, 0x3000        ; 12KB

    ; Get memory from OS
    mov rax, 9              ; mmap system call
    xor rdi, rdi              ; Let OS choose address
    mov rsi, 0x1000          ; 4KB
    mov rdx, 0x07              ; PROT_READ | PROT_WRITE
    mov r10, 0x22            ; MAP_PRIVATE | MAP_ANONYMOUS
    xor r8, r8
    syscall

    test rax, rax
    js memory_error

    ; Save heap pointer
    mov [heap_pointer], rax

    ; === Memory Operations ===
    ; Write to different memory areas
    mov dword [rdi], 0x12345678
    mov dword [rsi], 0x9ABCDEF0
    mov dword [rsi], 0x13579ACE
    mov dword [rdx], 0x2468ACE

    ; Read and display values
    call display_memory_contents

    ; Memory comparison
    mov rax, [rdi]          ; Get first dword
    mov rbx, [rsi]          ; Get second dword
    cmp rax, rbx            ; Compare values

    je values_equal
    values_not_equal:
        lea rsi, [rlf_memory_different_msg]
        call print_string
        jmp end_memory_management
    values_equal:
        lea rsi, [rlf_memory_same_msg]
        call print_string

    end_memory_management:
    ; Clean up
    ; Free allocated memory
    mov rax, 11          ; munmap
    mov rdi, [heap_pointer]
    mov rsi, 0x1000      ; Size
    syscall

    mov rax, r11          ; free stack allocation
    sub rsp, rax          ; Restore stack pointer

    pop rbp
    ret

display_memory_contents:
    lea rsi, [rlf_memory_contents]
    mov r10, 0              ; Counter

memory_display_loop:
    cmp r10, 4              ; Number of dwords
    jge memory_done

    lea rdi, [rlf_item_1]
    mov rax, [rdi]          ; Get value
    call print_hex
    lea rdi, [rlf_separator]
    inc r10
    jmp memory_display_loop

memory_done:
    lea rsi, [rlf_separator]
    call print_string

    ret

values_different:
    lea rsi, [rlf_memory_different_msg]
    call print_string
    ret

values_equal:
    lea rsi, [rlf_memory_same_msg]
    call print_string
    ret

; --- Advanced Pointer Examples ---
section .text
    global _start_pointers

_start_pointers:
    ; Create base pointers
    mov r12, 0x1000        ; Base pointer 1
    mov r13, 0x2000        ; Base pointer 2
    mov r14, 0x3000        ; Base pointer 3

    ; Create pointer array
    mov [pointer_array], r12
    mov [pointer_array + 8], r13
    [pointer_array + 16], r14

    ; Print pointer addresses
    lea rsi, [rlf_pointer_array_msg]
    call print_string

    lea rsi, [rlf_pointer_addr_1]
    mov rax, [pointer_array]
    call print_hex_with_prefix
    lea rsi, [rlf_pointer_addr_2]
    mov rax, [pointer_array + 8]
    call print_hex_with_prefix
    lea rsi, [rlf_pointer_addr_3]
    mov rax, [pointer_array + 16]
    call print_hex_with_prefix

    ; Pointer arithmetic
    lea r15, [pointer_array + 24]  ; R15 = array end
    sub r15, pointer_array        ; R15 = array start
    lea rsi, [rlf_pointer_arithmetic_msg]
    call print_string
    lea rsi, [rlf_array_end_addr]
    mov rax, r15
    call print_hex_with_prefix
    lea rsi, [rlf_array_start_addr]
    mov rax, [pointer_array]
    call print_hex_with_prefix

    ; Exit
    mov rax, 60
    xor rdi, rdi
    syscall

rlf_pointer_array_msg: db "Pointer array:", 0
rlf_pointer_addr_1: db "Pointer 1: ", 0
rlf_pointer_addr_2: db "Pointer 2: ", 0
rlf_pointer_addr_3: db "Pointer 3: ", 0
rlf_array_end_addr: db "Array end: ", 0

rlf_separator: db "; ", 10
rlf_pointer_arithmetic_msg: db "Pointer arithmetic (end - start): ", 0
rlf_array_start_addr: db "Array start: ", 0
rlf_array_end_addr: db "Array end: ", 0

section .data
    pointer_array: resq 4
    heap_pointer: resq 1

; --- Error Handling ---
section .text
global _start_error_handling

_start_error_handling:
    ; Try division by zero
    mov rax, 10
    xor rdx, rdx              ; Division by zero
    div idiv rdx              ; Divide RAX by RDX

    test rdx, rdx              ; Check if division was attempted
    jz division_success  ; No division attempted

division_error:
    lea rsi, [rlf_division_error_msg]
    call print_string
    jmp end_error_handling

division_success:
    lea rsi, [rlf_division_success_msg]
    call print_string
    jmp end_error_handling

    ; Access memory out of bounds
    mov rax, 0              ; Invalid pointer
    mov [rax], 42            ; This will cause segmentation fault
    jmp segmentation_fault

segmentation_fault:
    lea rsi, [rlf_seg_fault_msg]
    call print_string
    jmp end_error_handling

invalid_memory_access:
    lea rsi, [rlf_invalid_access_msg]
    call print_string

end_error_handling:
    mov rax, 60             ; Exit code
    xor rdi, rdi
    syscall

rlf_division_error_msg: db "Division by zero attempted!", 0
rlf_division_success_msg: "Division successful", 0
rlf_seg_fault_msg: db "Segmentation fault - invalid memory access!", 0
rlf_invalid_access_msg: db "Invalid memory access!", 0

; --- Performance Measurement ---
section .text
global _start_performance

_start_performance:
    ; Get start time
    mov rax, 201              ; sys_gettimeofday
    xor rdi, rdi
    lea rsi, [rel time_struct]
    syscall

    ; Perform some operations
    mov rcx, 1000           ; Initialize loop counter

performance_loop:
    ; Simple computation in loop
    imul r13, r13        ; Multiply
        add r13, r12        add r13, r11
        loop performance_loop
        dec rcx

    ; Get end time
    mov rax, 201              ; sys_gettimeofday
    xor rdi, rdi
    lea rsi, [rel time_struct]
    syscall

    Calculate time difference
    sub r13, [rsi]          ; end time start time (microseconds)
    sub r12, [rsi + 8]      ; start time seconds
    sub r13, [rsi + 8]      ; end time seconds

    ; Calculate operations per second
    mov r15, 1000
    imul r15, r12          ; Operations * time difference
    idiv r15, r13          ; Operations per second

    ; Print results
    lea rsi, [rlf_performance_msg]
    call print_string
    lea rsi, [rlf_time_elapsed_msg]
    call print_float
    lea rdi, [rlf_ops_per_sec_msg]
    call print_string

    mov rax, 60
    xor rdi, rdi
    syscall

section .data
    time_struct:
    .tv_sec dq 0
    .tv_usec dq 0

rlf_performance_msg: db "Performance Results:", 0
rlf_time_elapsed_msg: db "Time elapsed: %.2f s", 0
rlf_ops_per_sec_msg: db "Operations per second: %.2f ops/s", 0

rlf_separator: db "; ", 10

format_float: db "%.2f", 0

; --- Input/Output Operations ---
section .text
global _start_io_operations

_start_io_operations:
    ; Setup buffer
    sub rsp, 256
    lea rdi, [rsp]        ; Input buffer
    mov byte [rdi], 0       ; Initialize buffer

    ; Simple input simulation (commented out in real programs)
    ; mov rax, 0              ; sys_read
    ; mov rdi, 0              ; stdin
    ; lea rsi, [rsp]        ; buffer
    ; mov rdx, 255             ; max bytes to read
    ; syscall

    ; Simulate user input
    lea rdi, [rsp]
    mov rsi, [rel simulated_input]
    mov rdx, 20             ; max length
    call print_string
    syscall

    ; Read from standard input
    ;mov rax, 0              ; sys_read
    ;mov rdi, 0              ; stdin
    ;lea rsi, [rsp]        ; buffer
    ;mov rdx, 100             ; max bytes to read
    ;syscall

    ; Print what was read (simulated)
    lea rsi, [rlf_input_read_msg]
    call print_string
    mov rax, 1
    syscall

    jmp end_io_operations

end_io_operations:
    mov rax, 60             ; Exit
    xor rdi, rdi
    syscall

section .bss
    input_buffer: resb 256

rlf_input_read_msg: db "Input read (simulated): ", 0
simulated_input: db "John", 0
format_input: db "Name: %s", 0
rlf_separator: db "; ", 10

rlf_input_read_msg_len equ $ - rlf_input_read_msg

; --- String Manipulation ---
section .text
global _start_string_ops

_start_string_ops:
    ; Allocate working buffers
    sub rsp, 512              ; Allocate buffers
    lea rdi, [rsp]        ; Source buffer
    lea rsi, [rsp + 256]    ; Destination buffer

    ; Test different string operations
    lea rsi, [rel str1_msg]
    lea rsi, [rl str2_msg]
    lea rsi, [rl str_concat_msg]
    call print_string

    ; String concatenation
    strcat rsi, rdi
    strcat rsi, rsi + 256

    lea rsi, [rl concatenated_msg]
    call print_string

    ; String comparison
    lea rdi, [rl str1_msg]
    lea rsi, [rl str2_msg]
    call string_compare

    lea rsi, [rl_string_equal_msg]
    call print_string

    ; String length
    lea rsi, [rl str1_msg]
    mov rcx, rsi
    call get_string_length
    lea rsi, [rl str_len_msg]
    call print_string

    ; Exit
    add rsp, 512              ; Restore stack
    mov rax, 60
    xor rdi, rdi
    syscall

string_compare:
    strcmp rdi, rsi           ; Result: 0=equal, <0=less, >0=greater
    je strings_equal
    jl strings_less
    strings_greater:
        lea rsi, [rl_strings_greater_msg]
        call print_string
        jmp string_done

strings_less:
        lea rsi, [rl_strings_less_msg]
        call print_string
        jmp string_done

strings_equal:
        lea rsi, [rl_strings_equal_msg]
        call print_string

string_done:
    ret

get_string_length:
    xor rax, rax              ; Return string length
    ret

rlf_str1_msg: db "String 1: ", 0
rlf_str2_msg: db "String 2: ", 0
rlf_string_concat_msg: db "Concatenated: ", 0

rlf_string_equal_msg: db "Strings are equal", 0
rlf_strings_greater_msg: db "String 1 comes after String 2", 0
rlf_string_len_msg: db "String length: ", 0

rlf_separator: db "; ", 10
format_input: db "%s", 0
rlf_separator2: db "; ", 10

print_string:
    push rax
    push rdi
    push rsi
    mov rax, 1
    mov rdi, 1
    syscall
    pop rsi
    pop rdi
    pop rax
    ret

; --- Data Conversion ---
section .text
global _start_data_conversion

_start_data_conversion:
    ; Number to ASCII conversion examples
    numbers_to_convert = [10, -5, 0, 5, 100, 1000]

    ; Convert each number to string
    mov r10, 0              ; Index counter
    convert_numbers_loop:
    cmp r10, length(numbers_to_convert)
    jge convert_done

    mov eax, numbers_to_convert(r10)  ; Get current number
    mov ebx, eax              ; EBX = number as integer
    push rax                  ; Save register

    ; Handle negative numbers
    test ebx, ebx
    jge positive_number
    mov r14, '-'           ; Add minus sign for negative
    neg ebx             ; Negate
    jmp convert_to_ascii

positive_number:
    mov r14, '+'           ; Add plus sign for positive

convert_to_ascii:
    mov r15, 10              ; Max digits
    digit_count = 0
    digit_loop:
        xor rcx, rcx          ; Clear RCX
        mov r8, r15              ; RBX = remaining digits
        idiv rcx, 10          ; Extract last digit
        jz digit_done

        ; Convert digit to ASCII
        add r8, '0'         ; Add ASCII '0' to digit
        mov r13, r8              ; R13 = ASCII digit
        add r14, r13              ; R14 = ASCII digit
        inc digit_count
        cmp digit_count, 2     ; Have at least 2 digits
        jl single_digit

    single_digit:
        inc digit_count         ; Count = 1
        jmp digit_done

    digit_done:
    ; Terminate string
    mov byte [rsi], r14
    inc rsi                  ; Move buffer position
    jmp end_convert_numbers

positive_number:
    mov r15, 10              ; Max digits
    digit_count = 0
    digit_loop2:
        xor rcx, r15          ; Clear RCX
        idiv rcx, 10          ; Extract last digit
        jg digit_done2

    digit_done2:
    ; Terminate string
    mov byte [rsi], r14
    inc rsi                  ; Move buffer position
    jmp end_convert_numbers

    display_converted:
    lea rsi, [rlf_converted_msg]
    call print_string

    increment_index:
    inc r10
    jmp convert_numbers_loop

convert_done:
    pop rbx
    pop rax
    pop rax
    ret

display_converted:
    push rax
    push rdi
    push rsi
    add rsp, 32              ; Allocate space for 4 values

    ; Display converted numbers
    mov r10, 0              ; Index counter
    display_loop:
    cmp r10, length(numbers_to_convert)
    jge display_done

    lea rdi, [rlf_converted_msg]
    mov eax, numbers_to_convert(r10)
    call print_number
    inc r10
    jmp display_loop

display_done:
    add rsp, 32              ; Restore stack
    pop rsi
    pop rdi
    pop rax
    ret

end_convert_numbers:
    pop rbx
    pop rax
    ret

end_program:
    jmp _start_main

; --- File I/O with Buffering ---
section .text
global _start_file_io

_start_file_io:
    ; Setup
    sub rsp, 4096         ; Allocate large buffer
    lea rdi, [rsp]        ; Read buffer
    lea rsi, [rsi + 2048]  ; Write buffer

    ; Read from stdin with buffering
    mov rax, 0              ; sys_read
    mov rdi, 0              ; stdin
    lea rsi, [rsi]        ; Read buffer
    mov rdx, 4096            ; Large buffer
    syscall

    test rax, rax              ; Check for end of file
    jl end_file_io

    read_buffer_loop:
    ; Process read data
    lea rdi, [rlf_buffer_file_read_msg]
    call print_string
    add rsi, rdx          ; Move buffer position
    cmp rsi, [rsi + 4096]  ; Check end of buffer
    jl read_buffer_loop

    end_file_io:
    ; Calculate how much data was read
    lea rdi, [rsi]        ; Start address
    sub rdx, [rsi]        ; End address
    mov r15, rdx          ; Bytes read

    lea rsi, [rlf_bytes_read_msg]
    call print_string

    % Close stdin (if opened via sys_open)
    mov rax, 3              ; sys_close
    mov rdi, 0              ; stdin
    syscall

    jmp end_file_io

    % Write to stdout with buffering
write_buffered_output:
    ; Write buffer contents to stdout
    mov rax, 1              ; sys_write
    mov rdi, 1              ; stdout
    lea rsi, [rsi + 2048] ; Write buffer
    mov rdx, rdx          ; Number of bytes written
    syscall

    test rax, rax              ; Check for write error
    jl write_error

    lea rsi, [rlf_buffer_written_msg]
    call print_string
    jmp end_file_io

write_error:
    lea rsi, [rlf_write_error_msg]
    call print_string

end_file_io:
    add rsp, 4096         ; Restore stack
    pop rbp
    jmp end_program

rlf_buffer_file_read_msg: db "Read %d bytes from stdin", 0
rlf_bytes_read_msg: db "Bytes read: %d", 0
rlf_buffer_written_msg: db "Written %d bytes to stdout", 0
rlf_write_error_msg: db "Error writing to stdout", 0
rlf_separator: db "; ", 10
rlf_bytes_read_msg_len equ $ - rlf_bytes_read_msg
rlf_buffer_written_msg_len equ $ - rlf_buffer_written_msg

rlf_bytes_read_msg_len equ $ - rlf_bytes_read_msg
rlf_buffer_written_msg_len equ $ - rlf_buffer_written_msg
rlf_separator2: db "; ", 10

--- End of Examples ---

% Close all examples
end_section