请问这句是什么意思?add
本帖最后由 魔诀 于 2014-8-6 20:24 编辑下面这段代码是网络编程中编写客户端程序代码的一部分,主要功能是得到输入的内容并发送出去.elseif ax == IDOK
invoke lstrcpy,addr @stMsg.MsgUp.szContent,addr szText
invoke lstrlen,addr @stMsg.MsgUp.szContent
inc eax
mov @stMsg.MsgUp.dwLength,eax
add eax,sizeof MSG_HEAD+MSG_UP.szContent
mov @stMsg.MsgHead.dwLength,eax
mov @stMsg.MsgHead.dwCmdId,CMD_MSG_UP
invoke send,hSocket,addr @stMsg,@stMsg.MsgHead.dwLength,0
cmp eax,SOCKET_ERROR
add eax,sizeof MSG_HEAD+MSG_UP.szContent。这一句应该是计算信息总长度的。但是为什么要加上MSG_UP.szContent,
MSG_UP.szContent只是结构体中的一个变量,他只是一个地址而不是一个具体的表示长度的数值吧?还有就是,是不是和前面的
eax中的数值重复计算了?
下面是有关的结构体的定义:
MSG_HEAD struct
dwCmdId dw ? ;命令ID
dwLength dd ? ;整个数据包长度=数据包头部+数据包体
MSG_HEAD ends
MSG_UP struct
dwLength dd ? ;后面内容字段的长度
szContent db 256 dup (?) ;内容,不等长,长度由dwLength指定
MSG_UP ends
MSG_STRUCT struct
MsgHead MSG_HEAD <>
union
Login MSG_LOGIN <>
LoginResp MSG_LOGIN_RESP <>
MsgUp MSG_UP <>
MsgDown MSG_DOWN <>
ends
MSG_STRUCT ends
local @stMsg:MSG_STRUCT
建议把源码贴出来!这样会容易看懂些! {:2_27:} 汇编,,,,, 本帖最后由 魔诀 于 2014-8-6 16:04 编辑
下面是源码的全部:
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Sample code for < Win32ASM Programming 4th Edition>
; by 罗云彬, luoyunbin@hotmail.com
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Client.asm
; 使用 TCP 协议的聊天室例子程序 —— 客户端
; 本例子使用阻塞模式socket
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 使用 nmake 或下列命令进行编译和链接:
; ml /c /coff Client1.asm
; rc Client.rc
; Link /subsystem:windows Client1.obj Client.res
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386
.model flat, stdcall
option casemap :none ; case sensitive
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 数据
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
include wsock32.inc
includelib wsock32.lib
include _Message.inc
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; equ 数据
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ICO_MAIN equ 1000
DLG_MAIN equ 2000
IDC_SERVER equ 2001
IDC_USER equ 2002
IDC_PASS equ 2003
IDC_LOGIN equ 2004
IDC_LOGOUT equ 2005
IDC_INFO equ 2006
IDC_TEXT equ 2007
TCP_PORT equ 9999
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data?
hInstance dd ?
hWinMain dd ?
hSocket dd ?
dwLastTime dd ?
szServer db 16 dup (?)
szUserName db 12 dup (?)
szPassword db 12 dup (?)
szText db 256 dup (?)
.const
szErrIP db '无效的服务器IP地址!',0
szErrConnect db '无法连接到服务器!',0
szErrLogin db '无法登录到服务器,请检查用户名密码!',0
szSpar db ' : ',0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
include _SocketRoute.asm
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 通讯线程
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_WorkThread proc _lParam
local @stSin:sockaddr_in,@stMsg:MSG_STRUCT
local @szBuffer:byte
pushad
invoke GetDlgItem,hWinMain,IDC_SERVER
invoke EnableWindow,eax,FALSE
invoke GetDlgItem,hWinMain,IDC_USER
invoke EnableWindow,eax,FALSE
invoke GetDlgItem,hWinMain,IDC_PASS
invoke EnableWindow,eax,FALSE
invoke GetDlgItem,hWinMain,IDC_LOGIN
invoke EnableWindow,eax,FALSE
;********************************************************************
; 创建 socket
;********************************************************************
invoke RtlZeroMemory,addr @stSin,sizeof @stSin
invoke inet_addr,addr szServer
.if eax == INADDR_NONE
invoke MessageBox,hWinMain,addr szErrIP,NULL,MB_OK or MB_ICONSTOP
jmp _Ret
.endif
mov @stSin.sin_addr,eax
mov @stSin.sin_family,AF_INET
invoke htons,TCP_PORT
mov @stSin.sin_port,ax
invoke socket,AF_INET,SOCK_STREAM,0
mov hSocket,eax
;********************************************************************
; 连接到服务器
;********************************************************************
invoke connect,hSocket,addr @stSin,sizeof @stSin
.if eax == SOCKET_ERROR
invoke MessageBox,hWinMain,addr szErrConnect,NULL,MB_OK or MB_ICONSTOP
jmp _Ret
.endif
;********************************************************************
; 登录到服务器
;********************************************************************
invoke lstrcpy,addr @stMsg.Login.szUserName,addr szUserName
invoke lstrcpy,addr @stMsg.Login.szPassword,addr szPassword
mov @stMsg.MsgHead.dwLength,sizeof MSG_HEAD+sizeof MSG_LOGIN
mov @stMsg.MsgHead.dwCmdId,CMD_LOGIN
invoke send,hSocket,addr @stMsg,@stMsg.MsgHead.dwLength,0
cmp eax,SOCKET_ERROR
jz @F
invoke _RecvPacket,hSocket,addr @stMsg,sizeof @stMsg
or eax,eax
jnz @F
cmp @stMsg.MsgHead.dwCmdId,CMD_LOGIN_RESP
jnz @F
.if @stMsg.LoginResp.dbResult
@@:
invoke MessageBox,hWinMain,addr szErrLogin,NULL,MB_OK or MB_ICONSTOP
jmp _Ret
.endif
invoke GetDlgItem,hWinMain,IDC_LOGOUT
invoke EnableWindow,eax,TRUE
invoke GetDlgItem,hWinMain,IDC_TEXT
invoke EnableWindow,eax,TRUE
invoke GetTickCount
mov dwLastTime,eax
;********************************************************************
; 循环接收消息
;********************************************************************
.while hSocket
invoke GetTickCount
sub eax,dwLastTime
.break .if eax >= 60 * 1000
invoke _WaitData,hSocket,200 * 1000
.break .if eax == SOCKET_ERROR
.if eax
invoke _RecvPacket,hSocket,addr @stMsg,sizeof @stMsg
.break .if eax
.if @stMsg.MsgHead.dwCmdId == CMD_MSG_DOWN
invoke lstrcpy,addr @szBuffer,addr @stMsg.MsgDown.szSender
invoke lstrcat,addr @szBuffer,addr szSpar
invoke lstrcat,addr @szBuffer,addr @stMsg.MsgDown.szContent
invoke SendDlgItemMessage,hWinMain,IDC_INFO,LB_INSERTSTRING,0,addr @szBuffer
.endif
invoke GetTickCount
mov dwLastTime,eax
.endif
.endw
invoke GetDlgItem,hWinMain,IDOK
invoke EnableWindow,eax,FALSE
invoke GetDlgItem,hWinMain,IDC_TEXT
invoke EnableWindow,eax,FALSE
invoke GetDlgItem,hWinMain,IDC_LOGOUT
invoke EnableWindow,eax,FALSE
;********************************************************************
_Ret:
.if hSocket
invoke closesocket,hSocket
xor eax,eax
mov hSocket,eax
.endif
invoke GetDlgItem,hWinMain,IDC_SERVER
invoke EnableWindow,eax,TRUE
invoke GetDlgItem,hWinMain,IDC_USER
invoke EnableWindow,eax,TRUE
invoke GetDlgItem,hWinMain,IDC_PASS
invoke EnableWindow,eax,TRUE
invoke GetDlgItem,hWinMain,IDC_LOGIN
invoke EnableWindow,eax,TRUE
popad
ret
_WorkThread endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 主窗口程序
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcDlgMain proc uses ebx edi esi hWnd,wMsg,wParam,lParam
local @stWsa:WSADATA,@stMsg:MSG_STRUCT
mov eax,wMsg
;********************************************************************
.if eax == WM_COMMAND
mov eax,wParam
;********************************************************************
; 全部输入IP地址,用户名和密码后则激活"登录"按钮
;********************************************************************
.if (ax == IDC_SERVER) || (ax == IDC_USER) || (ax == IDC_PASS)
invoke GetDlgItemText,hWinMain,IDC_SERVER,addr szServer,sizeof szServer
invoke GetDlgItemText,hWinMain,IDC_USER,addr szUserName,sizeof szUserName
invoke GetDlgItemText,hWinMain,IDC_PASS,addr szPassword,sizeof szPassword
invoke GetDlgItem,hWinMain,IDC_LOGIN
.if szServer && szUserName && szPassword && !hSocket
invoke EnableWindow,eax,TRUE
.else
invoke EnableWindow,eax,FALSE
.endif
;********************************************************************
; 登录成功后,输入聊天语句后才激活"发送"按钮
;********************************************************************
.elseif ax == IDC_TEXT
invoke GetDlgItemText,hWinMain,IDC_TEXT,addr szText,sizeof szText
invoke GetDlgItem,hWinMain,IDOK
.if szText && hSocket
invoke EnableWindow,eax,TRUE
.else
invoke EnableWindow,eax,FALSE
.endif
;********************************************************************
.elseif ax == IDC_LOGIN
push ecx
invoke CreateThread,NULL,0,offset _WorkThread,0,NULL,esp
pop ecx
invoke CloseHandle,eax
;********************************************************************
.elseif ax == IDC_LOGOUT
@@:
.if hSocket
invoke closesocket,hSocket
xor eax,eax
mov hSocket,eax
.endif
;********************************************************************
.elseif ax == IDOK
invoke lstrcpy,addr @stMsg.MsgUp.szContent,addr szText
invoke lstrlen,addr @stMsg.MsgUp.szContent
inc eax
mov @stMsg.MsgUp.dwLength,eax
add eax,sizeof MSG_HEAD+MSG_UP.szContent
mov @stMsg.MsgHead.dwLength,eax
mov @stMsg.MsgHead.dwCmdId,CMD_MSG_UP
invoke send,hSocket,addr @stMsg,@stMsg.MsgHead.dwLength,0
cmp eax,SOCKET_ERROR
jz @B
invoke GetTickCount
mov dwLastTime,eax
invoke SetDlgItemText,hWinMain,IDC_TEXT,NULL
invoke GetDlgItem,hWinMain,IDC_TEXT
invoke SetFocus,eax
.endif
;********************************************************************
.elseif eax == WM_CLOSE
.if ! hSocket
invoke WSACleanup
invoke EndDialog,hWinMain,NULL
.endif
;********************************************************************
.elseif eax == WM_INITDIALOG
push hWnd
pop hWinMain
invoke LoadIcon,hInstance,ICO_MAIN
invoke SendMessage,hWnd,WM_SETICON,ICON_BIG,eax
invoke WSAStartup,101h,addr @stWsa
invoke SendDlgItemMessage,hWinMain,IDC_SERVER,EM_SETLIMITTEXT,15,0
invoke SendDlgItemMessage,hWinMain,IDC_USER,EM_SETLIMITTEXT,11,0
invoke SendDlgItemMessage,hWinMain,IDC_PASS,EM_SETLIMITTEXT,11,0
invoke SendDlgItemMessage,hWinMain,IDC_TEXT,EM_SETLIMITTEXT,250,0
;********************************************************************
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
_ProcDlgMain endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 程序开始
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke DialogBoxParam,eax,DLG_MAIN,NULL,offset _ProcDlgMain,0
invoke ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end start
这是 _SocketRoute.asm
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Sample code for < Win32ASM Programming 4th Edition>
; by 罗云彬, luoyunbin@hotmail.com
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 阻塞模式下使用的常用子程序
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;
;
;
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 在规定的时间内等待数据到达
; 输入:dwTime = 需要等待的时间(微秒)
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_WaitData proc _hSocket,_dwTime
local @stFdSet:fd_set,@stTimeval:timeval
mov @stFdSet.fd_count,1
push _hSocket
pop @stFdSet.fd_array
push _dwTime
pop @stTimeval.tv_usec
mov @stTimeval.tv_sec,0
invoke select,0,addr @stFdSet,NULL,NULL,addr @stTimeval
ret
_WaitData endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 接收规定字节的数据,如果缓冲区中的数据不够则等待
; 返回:eax = TRUE,连接中断或发生错误
; eax = FALSE,成功
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_RecvData proc _hSocket,_lpData,_dwSize
local @dwStartTime
mov esi,_lpData
mov ebx,_dwSize
invoke GetTickCount
mov @dwStartTime,eax
;********************************************************************
@@:
invoke GetTickCount ;查看是否超时
sub eax,@dwStartTime
cmp eax,10 * 1000
jge _Err
;********************************************************************
invoke _WaitData,_hSocket,100*1000 ;等待数据100ms
cmp eax,SOCKET_ERROR
jz _Err
or eax,eax
jz @B
invoke recv,_hSocket,esi,ebx,0
.if (eax == SOCKET_ERROR) || ! eax
_Err:
xor eax,eax
inc eax
ret
.endif
.if eax < ebx
add esi,eax
sub ebx,eax
jmp @B
.endif
xor eax,eax
ret
_RecvData endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 接收一个符合规范的数据包
; 返回:eax = TRUE (失败)
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_RecvPacket proc _hSocket,_lpBuffer,_dwSize
local @dwReturn
pushad
mov @dwReturn,TRUE
mov esi,_lpBuffer
assume esi:ptr MSG_STRUCT
;********************************************************************
; 接收数据包头部并检测数据是否正常
;********************************************************************
invoke _RecvData,_hSocket,esi,sizeof MSG_HEAD
or eax,eax
jnz _Ret
mov ecx,.MsgHead.dwLength
cmp ecx,sizeof MSG_HEAD
jb _Ret
cmp ecx,_dwSize
ja _Ret
;********************************************************************
; 接收余下的数据
;********************************************************************
sub ecx,sizeof MSG_HEAD
add esi,sizeof MSG_HEAD
.if ecx
invoke _RecvData,_hSocket,esi,ecx
.else
xor eax,eax
.endif
mov @dwReturn,eax
_Ret:
popad
assume esi:nothing
mov eax,@dwReturn
ret
_RecvPacket endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
本帖最后由 魔诀 于 2014-8-6 16:12 编辑
这是定义的结构体
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Sample code for < Win32ASM Programming 3rd Edition>
; by 罗云彬, http://www.win32asm.com.cn
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 使用 TCP 协议的聊天室例子程序
; 通讯链路传输的数据结构定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;
;
;
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
CMD_LOGIN equ 01h ; 客户端 ->服务器端,登录
CMD_LOGIN_RESP equ 81h ; 服务器端 -> 客户端,登录回应
CMD_MSG_UP equ 02h ; 客户端 -> 服务器端,聊天语句
CMD_MSG_DOWN equ 82h ; 服务器端 -> 客户端,聊天语句
CMD_CHECK_LINK equ 83h ; 服务器端 -> 客户端,链路检测
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据包定义方式
; 每个数据包以 MSG_HEAD + MSG_xxx 组成,整个长度填入 MSG_HEAD.dwLength
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;********************************************************************
; 数据包头部,所有的数据包都以 MSG_HEAD 开头
;********************************************************************
MSG_HEAD struct
dwCmdId dw ? ;命令ID
dwLength dd ? ;整个数据包长度=数据包头部+数据包体
MSG_HEAD ends
;********************************************************************
; 登录数据包(客户端->服务器端)
;********************************************************************
MSG_LOGIN struct
szUserName db 12 dup (?) ;用户登录ID
szPassword db 12 dup (?) ;登录密码
MSG_LOGIN ends
;********************************************************************
; 登录回应数据包(服务器端->客户端)
;********************************************************************
MSG_LOGIN_RESP struct
dbResult db ? ;登录结果:0=成功,1=用户名或密码错
MSG_LOGIN_RESP ends
;********************************************************************
; 聊天语句(客户端->服务器端):不等长数据包
;********************************************************************
MSG_UP struct
dwLength dd ? ;后面内容字段的长度
szContent db 256 dup (?) ;内容,不等长,长度由dwLength指定
MSG_UP ends
;********************************************************************
; 聊天语句(服务器端->客户端):不等长数据包
;********************************************************************
MSG_DOWN struct
szSender db 12 dup (?) ;消息发送者
dwLength dd ? ;后面内容字段的长度
szContent db 256 dup (?) ;内容,不等长,长度由dwLength指定
MSG_DOWN ends
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
MSG_STRUCT struct
MsgHead MSG_HEAD <>
union
Login MSG_LOGIN <>
LoginResp MSG_LOGIN_RESP <>
MsgUp MSG_UP <>
MsgDown MSG_DOWN <>
ends
MSG_STRUCT ends
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
青玄 发表于 2014-8-6 14:29
建议把源码贴出来!这样会容易看懂些!
把源码全贴出来了。 竟然用汇编实现。。真屌。。。 这个结构的大小加上后面那个字段的值再加上前面的eax 观看学习。。学习 让幸福如雨,洒在您心间 好复杂的东西 前段时间用win32汇编写了socket现在转C++了不想再用汇编了 add eax,sizeof MSG_HEAD+MSG_UP.szContent
不有一个sizeof么,sizeof就是求结构的长度,也就是地址的长度,然后俩个地址相加求出其尺寸啊 华彩篇章 发表于 2014-8-8 18:15
add eax,sizeof MSG_HEAD+MSG_UP.szContent
不有一个sizeof么,sizeof就是求结构的长度,也就是地址 ...
sizeof只求SMG_HEAD的字节长,MSG_UP.szContent是偏移量。已经搞明白了。 调试万能 到OD 里看一下值就明白了。。下次我也写个socket程序 我也不会求指教{:1_1:} cable5881 发表于 2014-8-9 08:02
我也不会求指教
在MASM的语法中“结构名.字段名”代表该字段在结构中的偏移量。 win32汇编还没看呢 I want more
页:
[1]
2