;运行效果
;win32汇编环境,按字节、双字等复制字符的操作
;这是汇编的优点之一。我们可以按字节、双字、四字、八字节等复制或挨个检查字符。
;有时候,在接收到的一串信息中,比如访问网站时,返回的字串里,有很多0值存在,用一般的字符串处理函数会把它当作结束符看待。这是错误的,因为这个0值只是一段信息的结束,后面还跟着很多的字串。
;有时候,访问网站时,返回的字串是UFT8编码的,这是不定长的字串,由某个字节的内容决定后面跟着的字串有几个字节,或有多长。我们必须分析每个字节的内容,决定后一步如何读取或分析。用其它的高级语言,反而变得更复杂,甚至无法这么低层的操作。
;在写网络爬虫时,一样可以按字节分析,把汉字与字母区别开来。
;很多的时候,显示出乱码,都是因为编码的问题导致的。比如字串是UNICODE编码的,按默认的ASCII去读取或发送,就成了乱码。
;我们首先需要知道,byte是字节(8位)、word是双字节(16位)、dword是四字节(32位),qword是八字节(64位)的概念。
;下面为asm文件
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386
.model flat,stdcall
option casemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定义;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib
; 自定义函数声明;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DlgProc proto :DWORD,:DWORD,:DWORD,:DWORD ;对话框窗口函数
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data
DlgName db "MyDialog",0
szCap db "提示",0
szEx db "ABCDEFGHIJKLMNOPQRST",0 ;要读取的字符串
.data?
hInstance HINSTANCE ?
.const
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Equ 等值定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ICO_MAIN equ 1000 ;图标
IDB01 equ 11 ;按钮控件标识符
IDB02 equ 12
IDB03 equ 13
IDB04 equ 14
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke DialogBoxParam, hInstance, ADDR DlgName,NULL, addr DlgProc, NULL
invoke ExitProcess,eax
DlgProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL @stPs:PAINTSTRUCT
LOCAL @stRect:RECT
LOCAL @hDc
LOCAL @szBuffer[256]:byte
.if uMsg == WM_INITDIALOG
invoke LoadIcon,hInstance,ICO_MAIN ;加载图标
invoke SendMessage,hWnd,WM_SETICON,ICON_BIG,eax
.elseif uMsg == WM_COMMAND
mov eax,wParam
.if eax == IDB01
mov bl,byte ptr [szEx+3] ;因为从0开始计数,取第4个字节则是+3,这里使用bl寄存器,它是8位寄存器,即1个字节.byte的意思是按字节复制
mov byte ptr [@szBuffer],bl
mov byte ptr [@szBuffer+1],0 ;第2个字节加0,即结束符
invoke MessageBox,NULL,addr @szBuffer,addr szCap,MB_OK
.elseif ax == IDB02
mov bx,word ptr [szEx+4] ;按双字节复制,这里使用bx,bx是16位寄存器,word是双字节,每字节为8位,双字即16位,要对应的上
mov word ptr [@szBuffer],bx
mov byte ptr [@szBuffer+2],0
invoke MessageBox,NULL,addr @szBuffer,addr szCap,MB_OK
.elseif ax == IDB03
mov ebx,dword ptr [szEx+4] ;按四字节复制
mov dword ptr [@szBuffer],ebx
mov byte ptr [@szBuffer+4],0
invoke MessageBox,NULL,addr @szBuffer,addr szCap,MB_OK
.elseif ax == IDB04
mov ebx,dword ptr [szEx] ;按八字节复制,这里分两次按4字节操作,因为现在用的是32位编译器,撑不上64位。不用追求64位的,那个还不完善,32位的精通了,一样实现目的。
mov dword ptr [@szBuffer],ebx
mov ebx,dword ptr [szEx+4]
mov dword ptr [@szBuffer+4],ebx
mov byte ptr [@szBuffer+8],0
invoke MessageBox,NULL,addr @szBuffer,addr szCap,MB_OK
.endif
.elseif uMsg == WM_PAINT
invoke BeginPaint,hWnd,addr @stPs
mov @hDc,eax
mov @stRect.left,20
mov @stRect.top,20
mov @stRect.right,200
mov @stRect.bottom,40
invoke DrawText,@hDc,addr szEx,-1,addr @stRect,DT_SINGLELINE or DT_LEFT or DT_VCENTER
invoke EndPaint,hWnd,addr @stPs
.elseif uMsg == WM_CLOSE
invoke EndDialog, hWnd,NULL
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
DlgProc endp
end start
;下面为rc文件内容
#include "resource.h" //提示缺少该文件,可以在资源里下载
#define ICO_MAIN 1000 //图标
#define IDB01 11
#define IDB02 12
#define IDB03 13
#define IDB04 14
ICO_MAIN ICON "Main.ico"
//定义对话框
MyDialog DIALOG 10, 10, 120, 130
STYLE DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
CAPTION "对话框程序模版"
BEGIN
PUSHBUTTON "复制第4个字节", IDB01, 10,40,100,14
PUSHBUTTON "复制第3个双字节", IDB02, 10,60,100,12
PUSHBUTTON "复制第2个四字节", IDB03, 10,80,100,14
PUSHBUTTON "复制第1个八字节", IDB04, 10,100,100,12
END