163 lines
2.8 KiB
ArmAsm
163 lines
2.8 KiB
ArmAsm
.code64
|
|
#include <asm/unistd.h>
|
|
#define _LINUX_POSIX_TYPES_H
|
|
#include <asm/socket.h>
|
|
|
|
#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 */
|