这是针对 x86 系统的。如果您想用于 x86_64 系统,请将 x86 寄存器更改为 x86_64。例如将“eax”更改为“rax”或将“esp”更改为“rsp”。并更改 eax(rax) 中的系统调用值,请参阅 https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md
[bits 32]
global _start
section .data
msg: db "Socket Failed To Create!",0xa,0
len: equ $-msg
msg1: db "Socket Created",0xa,0
len1: equ $-msg1
msg2: db "Recv Or Send Failed",0xa,0
len2: equ $-msg2
msg3: db "Shutdown Socket Failed",0xa,0
len3: equ $-msg3
DATASIZE: equ 5
SOCK_STREAM: equ 1
AF_INET: equ 2
AF_INET: equ 2
INADDR_ANY: equ 0
MSG_WAITALL: equ 0x100
MSG_DONTWAIT: equ 0x40
SHUT_RDWR: equ 2
SYS_SOCKET: equ 1 ; sys_socket(2)
SYS_BIND: equ 2 ; sys_bind(2)
SYS_CONNECT: equ 3 ; sys_connect(2)
SYS_LISTEN: equ 4 ; sys_listen(2)
SYS_ACCEPT: equ 5 ; sys_accept(2)
SYS_GETSOCKNAME:equ 6 ; sys_getsockname(2)
SYS_GETPEERNAME:equ 7 ; sys_getpeername(2)
SYS_SOCKETPAIR: equ 8 ; sys_socketpair(2)
SYS_SEND: equ 9 ; sys_send(2)
SYS_RECV: equ 10 ; sys_recv(2)
SYS_SENDTO: equ 11 ; sys_sendto(2)
SYS_RECVFROM: equ 12 ; sys_recvfrom(2)
SYS_SHUTDOWN: equ 13 ; sys_shutdown(2)
SYS_SETSOCKOPT: equ 14 ; sys_setsockopt(2)
SYS_GETSOCKOPT: equ 15 ; sys_getsockopt(2)
SYS_SENDMSG: equ 16 ; sys_sendmsg(2)
SYS_RECVMSG: equ 17 ; sys_recvmsg(2)
SYS_ACCEPT4: equ 18 ; sys_accept4(2)
SYS_RECVMMSG: equ 19 ; sys_recvmmsg(2)
SYS_SENDMMSG: equ 20 ; sys_sendmmsg(2)
struc sockaddr_in, -0x30
.sin_family: resb 2 ;2bytes
.sin_port: resb 2 ;2bytes
.sin_addr: resb 4 ;4bytes
.sin_zero: resb 8 ;8bytes
endstruc
struc socket, -0x40
.socketfd resb 4
.connectionfd resb 4
.count resb 4
.data resb DATASIZE
endstruc
section .text
_start:
push ebp
mov ebp, esp
sub esp, 0x400 ;1024byte
xor edx, edx ;or use cdq
;
; int socket(int domain, int type, int protocol);
; domain: The domain argument specifies a communication domain
;
push edx ; Push protocol
push dword SOCK_STREAM ; Push type
push dword AF_INET ; Push domain
mov ecx, esp ; ECX points to args
mov ebx, SYS_SOCKET ;
mov eax, 0x66 ; socketcall()
int 0x80
cmp eax, 0
jl .socket_failed
mov [ebp + socket.socketfd], eax
;
; fill struct sockaddr_in serv_addr;
;
mov word [ebp + sockaddr_in.sin_family], AF_INET
mov word [ebp + sockaddr_in.sin_port], 0x3905
mov dword [ebp + sockaddr_in.sin_addr], INADDR_ANY
push dword [ebp + sockaddr_in.sin_addr]
push word [ebp + sockaddr_in.sin_port]
push word [ebp + sockaddr_in.sin_family]
mov ecx, esp
;
; int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
;
push byte 0x10 ; sizeof(struct sockaddr)
push ecx ; pointer struct sockaddr
push dword [ebp + socket.socketfd]
mov ecx, esp ; ECX points to args
mov ebx, SYS_BIND ;
mov eax, 0x66
int 0x80
cmp eax, 0
jne .socket_failed
;
; int listen(int sockfd, int backlog);
;
push dword 0x10
push dword [ebp + socket.socketfd]
mov ecx, esp
mov ebx, SYS_LISTEN
mov eax, 0x66
int 0x80
cmp eax, 0
jne .socket_failed
;
; int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
;
xor ebx, ebx
push ebx
push ebx
push dword [ebp + socket.socketfd]
mov ecx, esp
mov ebx, SYS_ACCEPT
mov eax, 0x66
int 0x80
cmp eax, -1
je .socket_failed
mov [ebp + socket.connectionfd], eax
mov dword [ebp + socket.count], 0
.again:
lea edi, [ebp + socket.data]
mov ecx, DATASIZE
mov eax, 0
rep stosd
lea eax, [ebp + socket.data]
;
; ssize_t recv(int sockfd, const void *buf, size_t len, int flags);
;
push dword MSG_WAITALL
push dword DATASIZE
push eax
push dword [ebp + socket.connectionfd]
mov ecx, esp
mov ebx, SYS_RECV
mov eax, 0x66
int 0x80
cmp eax, 0
jle .recv_or_send_failed
mov edx, eax
lea ecx, [ebp + socket.data]
call printk
inc dword [ebp + socket.count]
cmp dword [ebp + socket.count], 5
jle .again
.break:
;
; int shutdown(int sockfd, int how);
;
push dword SHUT_RDWR
push dword [ebp + socket.socketfd]
mov ecx, esp
mov ebx, SYS_SHUTDOWN
mov eax, 0x66
int 0x80
cmp eax, 0
jne .shutdown_failed
;
; int close(int fd)
;
mov ebx, [ebp + socket.connectionfd]
mov eax, 0x06
int 0x80
cmp eax, 0
jne .shutdown_failed
jmp .success
.shutdown_failed:
mov edx, len3
mov ecx, msg3
call printk
jmp .end
.recv_or_send_failed:
mov edx, len2
mov ecx, msg2
call printk
jmp .end
.socket_failed:
mov edx, len
mov ecx, msg
call printk
jmp .end
.success:
mov edx, len1
mov ecx, msg1
call printk
jmp .end
.end:
leave
mov ebx,0 ;first syscall argument: exit code
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
ret
; EDX: message length
; ECX: pointer to message to write
printk:
pusha
mov ebx,1 ;first argument: file handle (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
popa
ret