MASM(32 位 asm)中的 Winsock 绑定函数错误
Winsock-bind function error In MASM(32 BIT asm)
首先,我很抱歉我的英语不好,英语不是我的第一语言。
所以,我正在尝试用 32 位汇编语言编写聊天程序,MASM。
现在,我正在编写服务器端代码,到目前为止我使用了 WSAStartUp 和 Socket - Windows API 函数,现在我正在尝试使用 Bind 函数。
绑定函数的link:https://msdn.microsoft.com/en-us/library/windows/desktop/ms737550(v=vs.85).aspx
这是我目前写的代码(我的问题写在代码后面):
.386
.MODEL Flat, STDCALL
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\Ws2_32.inc
includelib \masm32\lib\Ws2_32.lib
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
.DATA
Success db 'WSAStartUp Succseed!',0
NO_Success db 'WSAStartUp NOT Succseed....',0
Socketsu db 'Socket :(:(:(:(',0
SocketSuccess db 'Socket Success!! :)',0
Bindno db 'Bind Error',0
Bindyes db 'Bind Success! :)',0
LocalIP db "127.0.0.1",0
port dd 8020
.DATA?
wsadata db 400 dup (?) ;WSADATA struct that hold the information about the Windows Sockets implementation.(info ret from WSATSTARTUP)
flag dw ?
ListenSocket dd ?
SockAddrStruct db 30 dup (?)
;so sockaddr_in <?>
sockaddrs db 16 dup (?)
.CONST
wVersionRequested equ 0101h
.CODE
main:
;-------------------WSAStartUp-----------------------;
;Initialize the work with winsock (WS StartUp = WINSOCK START UP)
invoke WSAStartup,wVersionRequested, offset wsadata
.if eax!=0
invoke MessageBoxA,NULL,offset NO_Success,offset NO_Success,MB_OK
jmp End_Program
.else
invoke MessageBoxA,NULL,offset Success,offset Success,MB_OK
.endif
;-------------------Socket-----------------------;
;AF_INET - address family(in format: host,port) to likboa the type of addresses that the socket can communicate with
invoke socket,AF_INET,SOCK_STREAM,IPPROTO_TCP
.IF eax==INVALID_SOCKET
invoke MessageBoxA,NULL,offset Socketsu,offset Socketsu,MB_OK
jmp End_Program
.else
invoke MessageBoxA,NULL,offset SocketSuccess,offset SocketSuccess,MB_OK
mov [ListenSocket],eax
.ENDIF
;-------------------Bind-------------------------;
;SockAddr Struct:
mov eax,AF_INET
mov [dword ptr sockaddrs],eax
invoke htons,[port]
mov [dword ptr sockaddrs+2],eax
invoke inet_addr,[dword ptr LocalIP]
mov [dword ptr sockaddrs+4],eax
invoke bind,SIZEOF sockaddrs,offset sockaddrs,ListenSocket
.if eax==0
invoke MessageBoxA,NULL,offset Bindyes,offset Bindyes,MB_OK
.else
invoke MessageBoxA,NULL,offset Bindno,offset Bindno,MB_OK
.endif
End_Program:
invoke ExitProcess,0
end main
不知道是什么问题。但是当我 运行 代码时,我得到了我构建的 MessageBox says:Bind 错误。
我猜这是 sockaddrs 结构(我将值放入其中的方式)中的问题。但是我不知道我需要更改什么以及如何修复它。
我想也许可以使用 WSAGetLastError 函数来查看错误是什么,但我不知道如何打印函数 returns 的值并查看错误是什么(我无法输入调用MessageBox,一个参数EAX(保存returns值的寄存器)) .
有人可以帮我解决 'Bind' 部分的问题吗?
WSAGetLastError
你有几个问题。我将首先为您提供一种检索代表最后一个 WSAGetLastError
的消息的方法(它也适用于 GetLastError
)。 Win32 API方式是用FormatMessage
将WSAGetLastError
编辑的错误信息代码return进行转换。来自 MSDN 的关于 FormatMessage 的信息可以在 here, along with an example 中找到,类似于我们将使用的代码。它被定义为:
DWORD WINAPI FormatMessage(
In DWORD dwFlags,
In_opt LPCVOID lpSource,
In DWORD dwMessageId,
In DWORD dwLanguageId,
Out LPTSTR lpBuffer,
In DWORD nSize,
In_opt va_list *Arguments
);
在你的 .DATA?
区域,添加一个变量来存储缓冲区指针,我们将从 FormatMessage
:
return
lpErrorMsg dd ?
然后要检索并显示最后一个 WSA 错误,您可以在与套接字相关的调用(如 bind
)之后使用类似的东西:
.if eax==SOCKET_ERROR
invoke WSAGetLastError
invoke FormatMessageA, FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, eax, LANG_NEUTRAL, offset lpErrorMsg, 0, NULL
invoke MessageBoxA,NULL,lpErrorMsg,offset Bindno,MB_OK
.endif
错误修复
您的代码中存在许多问题。我观察到的第一个是 port
需要是一个 32 位整数,所以它应该被定义为:
port dd 8020
如果不进行此更改,htons
将无法正常工作,因为它需要一个 32 位整数。
下一个错误在这里:
invoke MessageBoxA,NULL,offset SocketSuccess,offset SocketSuccess,MB_OK
mov [ListenSocket],eax
您先调用 MessageBoxA
是在破坏 eax
。您可能打算先保存它:
mov [ListenSocket],eax
invoke MessageBoxA,NULL,offset SocketSuccess,offset SocketSuccess,MB_OK
此代码中似乎存在许多问题:
mov eax,AF_INET
mov [dword ptr sockaddrs],eax
这是不正确的,因为它适用于 32 位 Integer,我们需要一个 WORD(16 位)。应该是:
mov ax,AF_INET
mov [word ptr sockaddrs],ax
这也需要使用 16 位 WORD 存储在 sockaddrs+2
:
invoke htons,[port]
mov [dword ptr sockaddrs+2],eax
本来应该是:
invoke htons,[port]
mov [word ptr sockaddrs+2],ax
这是不正确的,因为我们不想取消对 LocalIP 的引用,我们只需要 LocalIP 的地址:
invoke inet_addr,[dword ptr LocalIP]
mov [dword ptr sockaddrs+4],eax
所以这似乎更正确:
invoke inet_addr, offset LocalIP
mov [dword ptr sockaddrs+4],eax
然后您将参数混淆为 bind
。你有:
invoke bind,SIZEOF sockaddrs,offset sockaddrs,ListenSocket
应该是:
invoke bind,ListenSocket,offset sockaddrs,SIZEOF sockaddrs
使用 sockaddr_in
的更简单方法
MASM32 定义了一个 sockaddr_in
,其中定义了所有字段。为了更轻松地使用此结构并使代码更具可读性,您可能需要考虑将 SockAddrStruct
更改为定义为(并清零):
SockAddrStruct sockaddr_in <0>
使用 SockAddrStruct
以这种方式定义后,您现在可以更改套接字代码以读取如下内容:
;-------------------Bind-------------------------;
;SockAddr Struct:
mov SockAddrStruct.sin_family,AF_INET
invoke htons, [port]
mov SockAddrStruct.sin_port,ax
invoke inet_addr, offset LocalIP
mov SockAddrStruct.sin_addr.S_un.S_addr, eax
invoke bind,ListenSocket,offset SockAddrStruct,SIZEOF SockAddrStruct
首先,我很抱歉我的英语不好,英语不是我的第一语言。 所以,我正在尝试用 32 位汇编语言编写聊天程序,MASM。
现在,我正在编写服务器端代码,到目前为止我使用了 WSAStartUp 和 Socket - Windows API 函数,现在我正在尝试使用 Bind 函数。
绑定函数的link:https://msdn.microsoft.com/en-us/library/windows/desktop/ms737550(v=vs.85).aspx
这是我目前写的代码(我的问题写在代码后面):
.386
.MODEL Flat, STDCALL
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\Ws2_32.inc
includelib \masm32\lib\Ws2_32.lib
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
.DATA
Success db 'WSAStartUp Succseed!',0
NO_Success db 'WSAStartUp NOT Succseed....',0
Socketsu db 'Socket :(:(:(:(',0
SocketSuccess db 'Socket Success!! :)',0
Bindno db 'Bind Error',0
Bindyes db 'Bind Success! :)',0
LocalIP db "127.0.0.1",0
port dd 8020
.DATA?
wsadata db 400 dup (?) ;WSADATA struct that hold the information about the Windows Sockets implementation.(info ret from WSATSTARTUP)
flag dw ?
ListenSocket dd ?
SockAddrStruct db 30 dup (?)
;so sockaddr_in <?>
sockaddrs db 16 dup (?)
.CONST
wVersionRequested equ 0101h
.CODE
main:
;-------------------WSAStartUp-----------------------;
;Initialize the work with winsock (WS StartUp = WINSOCK START UP)
invoke WSAStartup,wVersionRequested, offset wsadata
.if eax!=0
invoke MessageBoxA,NULL,offset NO_Success,offset NO_Success,MB_OK
jmp End_Program
.else
invoke MessageBoxA,NULL,offset Success,offset Success,MB_OK
.endif
;-------------------Socket-----------------------;
;AF_INET - address family(in format: host,port) to likboa the type of addresses that the socket can communicate with
invoke socket,AF_INET,SOCK_STREAM,IPPROTO_TCP
.IF eax==INVALID_SOCKET
invoke MessageBoxA,NULL,offset Socketsu,offset Socketsu,MB_OK
jmp End_Program
.else
invoke MessageBoxA,NULL,offset SocketSuccess,offset SocketSuccess,MB_OK
mov [ListenSocket],eax
.ENDIF
;-------------------Bind-------------------------;
;SockAddr Struct:
mov eax,AF_INET
mov [dword ptr sockaddrs],eax
invoke htons,[port]
mov [dword ptr sockaddrs+2],eax
invoke inet_addr,[dword ptr LocalIP]
mov [dword ptr sockaddrs+4],eax
invoke bind,SIZEOF sockaddrs,offset sockaddrs,ListenSocket
.if eax==0
invoke MessageBoxA,NULL,offset Bindyes,offset Bindyes,MB_OK
.else
invoke MessageBoxA,NULL,offset Bindno,offset Bindno,MB_OK
.endif
End_Program:
invoke ExitProcess,0
end main
不知道是什么问题。但是当我 运行 代码时,我得到了我构建的 MessageBox says:Bind 错误。
我猜这是 sockaddrs 结构(我将值放入其中的方式)中的问题。但是我不知道我需要更改什么以及如何修复它。
我想也许可以使用 WSAGetLastError 函数来查看错误是什么,但我不知道如何打印函数 returns 的值并查看错误是什么(我无法输入调用MessageBox,一个参数EAX(保存returns值的寄存器)) .
有人可以帮我解决 'Bind' 部分的问题吗?
WSAGetLastError
你有几个问题。我将首先为您提供一种检索代表最后一个 WSAGetLastError
的消息的方法(它也适用于 GetLastError
)。 Win32 API方式是用FormatMessage
将WSAGetLastError
编辑的错误信息代码return进行转换。来自 MSDN 的关于 FormatMessage 的信息可以在 here, along with an example 中找到,类似于我们将使用的代码。它被定义为:
DWORD WINAPI FormatMessage(
In DWORD dwFlags,
In_opt LPCVOID lpSource,
In DWORD dwMessageId,
In DWORD dwLanguageId,
Out LPTSTR lpBuffer,
In DWORD nSize,
In_opt va_list *Arguments
);
在你的 .DATA?
区域,添加一个变量来存储缓冲区指针,我们将从 FormatMessage
:
lpErrorMsg dd ?
然后要检索并显示最后一个 WSA 错误,您可以在与套接字相关的调用(如 bind
)之后使用类似的东西:
.if eax==SOCKET_ERROR
invoke WSAGetLastError
invoke FormatMessageA, FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, eax, LANG_NEUTRAL, offset lpErrorMsg, 0, NULL
invoke MessageBoxA,NULL,lpErrorMsg,offset Bindno,MB_OK
.endif
错误修复
您的代码中存在许多问题。我观察到的第一个是 port
需要是一个 32 位整数,所以它应该被定义为:
port dd 8020
如果不进行此更改,htons
将无法正常工作,因为它需要一个 32 位整数。
下一个错误在这里:
invoke MessageBoxA,NULL,offset SocketSuccess,offset SocketSuccess,MB_OK
mov [ListenSocket],eax
您先调用 MessageBoxA
是在破坏 eax
。您可能打算先保存它:
mov [ListenSocket],eax
invoke MessageBoxA,NULL,offset SocketSuccess,offset SocketSuccess,MB_OK
此代码中似乎存在许多问题:
mov eax,AF_INET
mov [dword ptr sockaddrs],eax
这是不正确的,因为它适用于 32 位 Integer,我们需要一个 WORD(16 位)。应该是:
mov ax,AF_INET
mov [word ptr sockaddrs],ax
这也需要使用 16 位 WORD 存储在 sockaddrs+2
:
invoke htons,[port]
mov [dword ptr sockaddrs+2],eax
本来应该是:
invoke htons,[port]
mov [word ptr sockaddrs+2],ax
这是不正确的,因为我们不想取消对 LocalIP 的引用,我们只需要 LocalIP 的地址:
invoke inet_addr,[dword ptr LocalIP]
mov [dword ptr sockaddrs+4],eax
所以这似乎更正确:
invoke inet_addr, offset LocalIP
mov [dword ptr sockaddrs+4],eax
然后您将参数混淆为 bind
。你有:
invoke bind,SIZEOF sockaddrs,offset sockaddrs,ListenSocket
应该是:
invoke bind,ListenSocket,offset sockaddrs,SIZEOF sockaddrs
使用 sockaddr_in
的更简单方法MASM32 定义了一个 sockaddr_in
,其中定义了所有字段。为了更轻松地使用此结构并使代码更具可读性,您可能需要考虑将 SockAddrStruct
更改为定义为(并清零):
SockAddrStruct sockaddr_in <0>
使用 SockAddrStruct
以这种方式定义后,您现在可以更改套接字代码以读取如下内容:
;-------------------Bind-------------------------;
;SockAddr Struct:
mov SockAddrStruct.sin_family,AF_INET
invoke htons, [port]
mov SockAddrStruct.sin_port,ax
invoke inet_addr, offset LocalIP
mov SockAddrStruct.sin_addr.S_un.S_addr, eax
invoke bind,ListenSocket,offset SockAddrStruct,SIZEOF SockAddrStruct