; このサーバーのコードははFreeBSD向けに書きました。 ; Linuxに実行するには、syscall番号を変更して下さい。 section .data filename db "./www/index.html", 0x0 at_fd dq -0x64 listen_msg db "サーバーは http://0.0.0.0:8000/ で実行中・・・", 0xa, 0x0 listen_len equ $-listen_msg-1 http_header db "HTTP/1.1 200 OK", 0xd, 0xa db "Content-Type: text/html", 0xd, 0xa db "Connection: close", 0xd, 0xa db "Content-Length: " clen_str db " ", 0xd, 0xa, 0xd, 0xa, 0x0 notfound db "HTTP/1.1 404 Not Found", 0xd, 0xa, db "Content-Length: 0", 0xd, 0xa, 0xd, 0xa, 0x0 section .bss sock resq 0x1 ; サーバーソケット clientfd resq 0x1 ; クライアントソケット filefd resq 0x1 file_size resb 0x400 ; HTMLファイルサイズ file_buf resb 0x20000 ; 128 KiB req_buf resb 0x1000 ; 4 KiB addr resb 0x10 ; sockaddr_in ストラクチャー section .text %include "file.s" %include "u64todec.s" global _start _start: mov rax, 4 ; sys_write mov rdi, 1 ; stdout mov rsi, listen_msg mov rdx, listen_len syscall ; ソケットの作成 mov rax, 97 ; sys_socket mov rdi, 2 ; PF_INET mov rsi, 1 ; SOCK_STREAM mov rdx, 0 ; プロトコール syscall cmp rax, 0 jl error_exit mov [sock], rax ; 0.0.0.0:8000 にバインド mov word [addr], 2 ; sin_family = AF_INET mov word [addr+2], 0x401f ; sin_port = 8000 (ポート番号)、ネットワークのバイト列:0x1f40 ;mov dword [addr+4], 0x0100007f ; sin_addr = 127.0.0.1(リトルエンディアンで) mov dword [addr+4], 0 ; sin_addr = INADDR_ANY = 0.0.0.0 mov qword [addr+8], 0 ; パッディング ; バインド mov rax, 104 ; sys_bind mov rdi, [sock] mov rsi, addr mov rdx, 0x10 syscall cmp rax, 0 jne error_exit ; リッスン mov rax, 106 ; sys_listen mov rdi, [sock] mov rsi, 0xa ; バックログ syscall cmp rax, 0 jne error_exit ; HTMLファイルをメモリに読み込み(一回だけ) call load_file test rax, rax jnz error_exit ; ファイルを見つけなければ、エラーで終了する accept_loop: ; 接続の受け取り ; mov rax, 30 ; sys_accept mov rax, 541 ; sys_accept4 mov rdi, [sock] mov rsi, 0 mov rdx, 0 mov r10, 0 ; フラグ=0 syscall cmp rax, 0 jl loop_continue mov [clientfd], rax ; リクエストの読み込み mov rax, 3 ; sys_read mov rdi, [clientfd] mov rsi, req_buf mov rdx, 0xfff syscall ; ヘッダーの送信 ; Content-Length文字から mov rax, [file_size] mov rdi, clen_str call u64_to_dec mov rax, 4 ; sys_write mov rdi, [clientfd] mov rsi, http_header mov rdx, clen_str + 20 - http_header ; ヘッダーの長さ(CRLF含む) syscall ; ファイル内容の送信 mov rax, 4 ; sys_write mov rdi, [clientfd] mov rsi, file_buf mov rdx, [file_size] syscall ; クライアントの終了 mov rax, 6 ; sys_close mov rdi, [clientfd] syscall loop_continue: jmp accept_loop ; 終了(CTRL+C) mov rax, 1 ; sys_exit xor rdi, rdi syscall error_exit: mov rax, 1 ; sys_exit mov rdi, 1 syscall