Created
October 22, 2024 18:30
-
-
Save morkev/6aef38dfca7317fe05c51e5cd8e18995 to your computer and use it in GitHub Desktop.
Assembly code to dynamically respond to multi-processed HTTP GET requests
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| .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