🎯 Рекомендуемые коллекции
Балансированные коллекции примеров кода из различных категорий, которые вы можете исследовать
Примеры Ассемблера
Основные примеры программирования на Ассемблере для низкоуровнего программирования и архитектуры компьютера
💻 Ассемблер 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