x64汇编实现的多线程web server
一个web server,使用x64汇编
代码和注释如下,还是比较丑陋的
.intel_syntax noprefix
.globl _start
.section .text
_start:
socket:
mov rax, 0x29
mov rdi, 2
mov rsi, 1
mov rdx, 0
syscall
mov r14, rax
bind:
mov rdi, rax # 将socket 的fd mov到rdi
mov rax, 0x31
lea rsi, [socket_addr]
mov rdx, 16
syscall
listen:
mov rax, 0x32
mov rdi, 3
mov rsi, 0
syscall
conn_loop:
accept:
mov rax, 0x2b
mov rdi, 3
mov rsi, 0
mov rdx, 0
syscall
mov r15, rax
# fork child
# 39 - - -
mov rax, 0x39
syscall
cmp rax, 0
je child_process
# 3 unsigned int fd
mov rdi, r15
mov rax, 3
syscall # close accpet fd
jmp accept
child_process:
mov rdi, r14
mov rax, 3
syscall # close scock fd
read:
mov rdi, r15 # we read from the accepted connection, so we use that file descriptor
sub rsp, 0x400 # setting up the stack as the buffer variable
mov rsi, rsp
mov rdx, 0x400 # upto how many bytes can be read
xor rax, rax # 0 is the syscall value for read()
syscall # read(conn, *buf, 1024)
mov r14, rax # 保存长度
# 根据第一个单词来判断是否是POST
cmp byte ptr [rsp], 71
jne post
get:
lea rdi, [rsp + 4] # 跳过"Get "
xor rcx, rcx
# find filename
find_filename_get:
cmp byte ptr [rdi + rcx], 0x20 # 找到下一个空格
je end_filename_get
inc rcx
jmp find_filename_get
end_filename_get:
mov byte ptr [rdi + rcx], 0x0 # 将空格转为0
# open_file:
mov rsi, 0 # O_RDONLY
mov rax, 0x2
syscall
mov r14, rax
# read_file:
# unsigned int fd char *buf size_t count
mov rdi, r14
sub rsp, 0x1000
mov rsi, rsp
mov rdx, 0x1000
mov rax, 0
syscall # read
mov r14, rax # 保存长度
# closefd:
mov rax, 3
syscall
# write_static_response:
mov rax, 1 # write syscall
mov rdi, 4
lea rsi, [response]
mov rdx, 19
syscall
# write_file_content:
# 1 unsigned int fd const char *buf size_t count
mov rdi, r15
mov rsi, rsp
mov rdx, r14
mov rax, 1
syscall # write file
jmp close_accept
post:
# find filename
lea rdi, [rsp + 4] # 跳过"Get "
xor rcx, rcx
# 找到文件名
lea rdi, [rsp + 5] # 跳过"Post "
xor rcx, rcx
# find filename
find_filename:
cmp byte ptr [rdi + rcx], 0x20 # 找到下一个空格
je end_filename
inc rcx
jmp find_filename
end_filename:
mov byte ptr [rdi + rcx], 0x0 # 将空格转为0
# 找到头长度
lea rdi, [rsp] # rdi
xor rdx, rdx
find_header_length:
lea rsi, [end_string] # 将\r\n\r\n拷贝到rsi
mov rcx, 4
repe cmpsb # 重复比较字节直到RCX=0或字节不等
jz end_header_length
inc rdx
lea rdi, [rsp]
add rdi, rdx
jmp find_header_length
end_header_length:
add rdx, 4 # 正文开始的地方
mov r8, rsp # 保存开始的地方
add r8, rdx
mov r9, r14 # 总长度
sub r9, rdx # 保存正文的长度
# 打开文件
# 2 const char *filename int flags umode_t mode
open_file:
lea rdi, [rsp+5] # 文件名
mov rsi, 00000001 # O_WRONLY
xor rsi, 00000100 # O_CREAT
mov rdx, 0777
mov rax, 0x2
syscall
mov r10, rax
# 写回正文内存
write_file_content:
# 1 unsigned int fd const char *buf size_t count
mov rdi, r10
mov rsi, r8
mov rdx, r9
mov rax, 1
syscall # write 正文
# close file_fd
mov rdi, r10
mov rax, 3
syscall
write_static_response:
mov rax, 1 # write syscall
mov rdi, r15
lea rsi, [response]
mov rdx, 19
syscall
close_accept:
mov rdi, r15
mov rax, 3
syscall # close accept fd
# jmp conn_loop
exit:
mov rdi, 0
mov rax, 0x3c
syscall
.section .data
socket_addr:
.word 2 # AF_INET
.word 0x5000 # htons(80)
.long 0 #
.zero 8
response: .ascii "HTTP/1.0 200 OK\r\n\r\n"
end_string: .ascii "\r\n\r\n"
编译方式
gcc -nostdlib server.s -o server
浙公网安备 33010602011771号