.code64 #include #define _LINUX_POSIX_TYPES_H #include #define STDIN 0 #define STDOUT 1 #define STDERR 2 #define PF_INET 2 #define AF_INET PF_INET #define SOCK_STREAM 1 #define CLONE_PARENT 0x00008000 #define PORT 20335 .section .rodata greeting: .ascii "Welcome to the minimalistic echo server!\n" .ascii "It is written in pure assembly, and it don't use the standard library, only raw system calls.\n" .ascii "\n" .ascii "To exit, press Ctrl+C, as usual\n" .ascii "\n" .set greeting_len, .-greeting message: .ascii "Client connected\n" .set message_len, .-message errstr: .ascii "Error happened\n" .set errstr_len, .-errstr true_val: .quad 1 .set true_val_len, .-true_val myaddr: .hword AF_INET port: .byte (PORT >> 8) & 0xFF, (PORT & 0xFF) addr: .byte 0, 0, 0, 0 .set myaddr_len, 16 .extern passthru .extern write_buf #define server_socket %rbx #define connection_socket %r12 .text .global _start _start: movq $STDOUT, %rdi movq $greeting, %rsi movq $greeting_len, %rdx call write_buf movq $__NR_socket, %rax movq $PF_INET, %rdi movq $SOCK_STREAM, %rsi movq $0, %rdx syscall cmp $-1, %rax jz error movq %rax, server_socket movq $__NR_setsockopt, %rax movq server_socket, %rdi movq $SOL_SOCKET, %rsi movq $SO_REUSEADDR, %rdx movq $true_val, %r10 movq $true_val_len, %r8 syscall test %rax, %rax jnz error movq $__NR_bind, %rax movq server_socket, %rdi movq $myaddr, %rsi movq $myaddr_len, %rdx syscall test %rax, %rax jnz error movq $__NR_listen, %rax movq server_socket, %rdi movq $8, %rsi syscall test %rax, %rax jnz error loop: movq $__NR_accept, %rax movq server_socket, %rdi movq $0, %rsi movq $0, %rdx movq $0, %r10 syscall cmp $-1, %rax jz error movq %rax, connection_socket movq $STDOUT, %rdi movq $message, %rsi movq $message_len, %rdx call write_buf movq $__NR_clone, %rax movq $CLONE_PARENT, %rdi movq $0, %rsi movq $0, %rdx movq $0, %r10 movq $0, %r8 syscall /* fork! (through clone()) */ cmp $-1, %rax jz error test %rax, %rax jz child /* we're in the parent if we reach this line */ movq $__NR_close, %rax movq connection_socket, %rdi syscall test %rax, %rax jnz error jmp loop exit: movq $__NR_close, %rax movq server_socket, %rdi syscall test %rax, %rax jnz error movq $__NR_exit, %rax movq $0, %rdi syscall /* this line is unreachable */ error: movq $__NR_write, %rax movq $STDOUT, %rdi movq $errstr, %rsi movq $errstr_len, %rdx syscall movq $__NR_exit, %rax movq $1, %rdi syscall /* this line is unreachable */ child: /* we're in the child if we reach this line */ movq connection_socket, %rdi movq connection_socket, %rsi call passthru movq $__NR_close, %rax movq connection_socket, %rdi syscall movq $__NR_exit, %rax movq $0, %rdi syscall /* this line is unreachable */