Skip to content

Instantly share code, notes, and snippets.

@morkev
Created October 22, 2024 18:30
Show Gist options
  • Select an option

  • Save morkev/6aef38dfca7317fe05c51e5cd8e18995 to your computer and use it in GitHub Desktop.

Select an option

Save morkev/6aef38dfca7317fe05c51e5cd8e18995 to your computer and use it in GitHub Desktop.
Assembly code to dynamically respond to multi-processed HTTP GET requests
.intel_syntax noprefix
.global _start
.section .text
_start:
# create socket
mov rdi, 2 # AF_INET
mov rsi, 1 # SOCK_STREAM
xor rdx, rdx # IPPROTO_IP
mov rax, 41 # sys_socket
syscall
mov r8, rax # save the socket fd in r8
# bind
push 0 # padding
push 0 # INADDR_ANY
mov word ptr [rsp+2], 0x5000 # port 80 (network byte order)
mov word ptr [rsp], 2 # AF_INET
mov rdi, r8
mov rsi, rsp
mov rdx, 16
mov rax, 49 # sys_bind
syscall
add rsp, 16
# listen
mov rdi, r8
mov rsi, 0 # backlog
mov rax, 50 # sys_listen
syscall
accept_loop:
# accept new connection
mov rdi, r8
xor rsi, rsi
xor rdx, rdx
mov rax, 43 # sys_accept
syscall
mov r9, rax # save client fd
# fork a new process
mov rax, 57 # sys_fork
syscall
cmp rax, 0
je handle_request # child process handles the request
# parent process
mov rdi, r9
mov rax, 3 # sys_close
syscall # close client fd in parent
jmp accept_loop # parent goes back to accepting
handle_request:
# child process handles the connection
mov rdi, r8
mov rax, 3 # sys_close
syscall # close listening socket in child
# read request
mov rdi, r9
lea rsi, [buffer]
mov rdx, 1024
mov rax, 0 # sys_read
syscall
# parse HTTP request to get file path
lea rsi, [buffer + 4] # skip "GET "
lea rdi, [file_path]
mov rcx, 256 # max path length
parse_path:
cmp byte ptr [rsi], 0x20 # check for space
je done_parsing
cmp rcx, 0
je done_parsing
mov al, byte ptr [rsi]
mov byte ptr [rdi], al
inc rsi
inc rdi
dec rcx
jmp parse_path
done_parsing:
mov byte ptr [rdi], 0 # null terminate path
# open file
lea rdi, [file_path]
xor rsi, rsi # O_RDONLY
mov rax, 2 # sys_open
syscall
cmp rax, 0
js file_not_found
mov r10, rax # save fd
# read file
mov rdi, r10
lea rsi, [file_content]
mov rdx, 1024
mov rax, 0 # sys_read
syscall
push rax # save bytes read
# close file
mov rdi, r10
mov rax, 3 # sys_close
syscall
# send header
mov rdi, r9
lea rsi, [response_header]
mov rdx, 19
mov rax, 1 # sys_write
syscall
# send file content
pop rdx # restore bytes read as length
mov rdi, r9
lea rsi, [file_content]
mov rax, 1 # sys_write
syscall
jmp exit_child
file_not_found:
# send 404
mov rdi, r9
lea rsi, [not_found_response]
mov rdx, 26
mov rax, 1 # sys_write
syscall
exit_child:
# close client socket
mov rdi, r9
mov rax, 3 # sys_close
syscall
# exit child process
xor rdi, rdi
mov rax, 60 # sys_exit
syscall
.section .data
response_header: .ascii "HTTP/1.0 200 OK\r\n\r\n"
not_found_response: .ascii "HTTP/1.0 404 Not Found\r\n\r\n"
.section .bss
buffer: .space 1024
file_path: .space 256
file_content: .space 1024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment