win32汇编 实现UNIX文件格式转换WINDOWS文件格式 的功能
来源:互联网 发布:微信直播 阿里云 编辑:程序博客网 时间:2024/05/16 14:19
我们应该都知道UNIX环境下的文本文档中的回车加换行是直接由 "0ah" 实现的,而windows环境下的回车换行需要"0dh,0ah" 实现,所以如果把UNIX环境下的文本文档拿过来在WINDOWS环境下查看,那么文本的显示格式就乱了,结果是windows读不懂UNIX环境下的换行符,他以为是一行,事实也就是文本显示的就是一行,只能靠水平滚动条来回拖动查看,的确看着不爽,这次利用WIN32汇编语言 结合windows环境下内存管理的内容实现将UNIX文件格式转换为windows环境下的文件格式 的功能。下面看一下实现该功能的几个分步操作。
上面就是实现该功能的具体分支,下面首先来看一下资源文件中的问题:
资源文件中在使用ResEdit工具编写的时候,在对话框的风格中总会有一个风格DS-SHELLFONT,这个风格总是无效的,在用RadASM编译ResEdit工具编写的资源脚本的时候总会出现未找到定义的风格DS_SHELLFONT
也就是说在头文件的一些定义中并没有该风格的定义,总会出错,然后我果断的把这个风格从资源代码中移除。。。,结果呢,资源脚本可以编译运行了,那么这个风格到底是几个意思,如果要想用它的话怎么办呢?
我们还是来看一下MSDN博客是怎么说的,下面是连接:https://blogs.msdn.microsoft.com/oldnewthing/20050204-00/?p=36523/
具体可以参考一下,说的貌似很有道理,文件的版本需要更高才可以。
资源文件就这么多问题其他的就是以前常用的操作了,很熟练了。下面具体看一下资源脚本代码:
/
/ Generated by ResEdit 1.6.6// Copyright (C) 2006-2015// http://www.resedit.net#include <windows.h>#include <commctrl.h>#include <richedit.h>#include "resource.h"//// Dialog resources//LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRALIDD_DIALOG1 DIALOG 0, 0, 186, 95STYLE DS_3DLOOK | DS_CENTER | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFONT | WS_CAPTION | WS_VISIBLE | WS_GROUP | WS_TABSTOP | WS_POPUP | WS_SYSMENUCAPTION "UNIX Text file -> PC Text file"FONT 8, "Ms Shell Dlg"{ PUSHBUTTON "开始", IDOK, 127, 70, 46, 18, 0, WS_EX_DLGMODALFRAME PUSHBUTTON "浏览", IDC_BROWSE, 49, 70, 44, 18, NOT WS_TABSTOP | BS_VCENTER | BS_MULTILINE, WS_EX_DLGMODALFRAME | WS_EX_STATICEDGE LTEXT "文件名", 0, 17, 20, 43, 11, SS_LEFT, WS_EX_LEFT EDITTEXT IDC_FILE, 50, 18, 135, 16, ES_AUTOHSCROLL, WS_EX_DLGMODALFRAME | WS_EX_ACCEPTFILES}//// Icon resources//LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRALIDI_ICON1 ICON "icon2.ico"
本来想上传资源文件显示的截图的,但是上传文件时老出错误,就不传了。
下面看一下实现程序代码中遇到的问题:
这次程序中首先遇到的问题就是在处理缓冲区中的一单行的文本的时候,好多问题,下面来看一下子程序
_FormatText proc uses esi _lpData,_dwSize,_hFile ;首先该子程序需要三个参数,该子函数在_ProcFile()子程序中调用,_lpdata 就是将 一行文本读入到缓 冲区中,_lpData指向这个缓冲区,_dwSize 指向实际读入的 字节数,_hFile就是文件名只不过这个 文件名是存放在缓冲区中 LOCAL @szBuffer[128]:byte,@dwBytesWrite mov esi,_lpData ;esi寄存器作为源操作内容存放的开始地址 mov ecx,_dwSize ;作为循环的计数 lea edi,@szBuffer ;另开一个缓冲区将其地址存放到目的寄存器edi中 xor edx,edx cld ;将0标志位清零,表示传递数据的时候地址递增, std命令则相反。_LoopBegin: ;一个标志 ,为了方便 or ecx,ecx ;或运算 其实就是ecx的值 jz _WriteLine lodsb ;把esi寄存器中的内容从头开始依次放到al中,与stosb对应,stosb将al的 内容依次放到edi中 dec ecx cmp al,0dh jz _LoopBegin cmp al,0ah jz _LineEnd stosb ;stosb将al的内容依次放到edi中,与lodsb对应 inc edx cmp edx,sizeof @szBuffer-2 ;这个子程序处理的是一行文本而且这一行文本就放在缓冲区@szBuffer中,一 行文本最后就是0dh, 0ah,回车加换行,正好两个字节,如果处理的字节数edx大于等于缓冲区 总字节数减去2的值,那么 表示这一行的文本已经处理完了。 jae _WriteLine ;大于等于则跳转 jmp _LoopBegin_LineEnd: mov ax,0a0dh stosw ;同stosb指令一个属性,只不过stosw是将ax中的内容放到edi中,与 lodsw对应 inc edx ;这里讲edx计数器连续自加两次,原因就是stosw将两个字节(0dh, 0ah)读入到了edi中,处理了 两个字节 inc edx_WriteLine: push ecx .if edx invoke WriteFile,_hFile,addr @szBuffer,edx,addr @dwBytesWrite,NULL .endif lea edi,@szBuffer ;上面代码中已经将@szBuffer的地址传递给edi在这里再传一次还有必要么?经过我的测试发现,确实需要再传一 次,不然的话程序会出错退出 xor edx,edx pop ecx or ecx,ecx jnz _LoopBegin ret_FormatText endp
关于上面子程序的介绍应该已经很清楚了。
下面来看一下另一个问题:
以前也遇见过这个问题记不清楚了也没有解决,今天在这个程序中也用到了这个指令,如下一段代码所示:
.while TRUE lea esi,@szReadBuffer invoke ReadFile,@hFile,esi,sizeof @szReadBuffer,addr @dwBytesRead,0 .break .if ! @dwBytesRead ;这一行 invoke _FormatText,esi,@dwBytesRead,@hFileNew .endw
如上面标注的一行 .break .if [条件] 这个语句
具体的意思就是:如果满足.if 中的条件则终止循环,跳出循环执行下面的语句。
与值对关的还有.continue .if [条件] 如果满足条件则结束当前语句,从新循环。
说完了这两个问题,下面来详细看一下程序实现代码:
.386 .model flat, stdcall option casemap :none include windows.incinclude user32.incincludelib user32.libinclude kernel32.incincludelib kernel32.libinclude comdlg32.incincludelib comdlg32.libIDI_ICON1 equ 102IDD_DIALOG1 equ 103IDC_BROWSE equ 40000IDC_FILE equ 40001 .data?hInstance dd ?hWinMain dd ?szFileName db MAX_PATH dup (?) .constszFileExt db '文本文件',0,'*.txt',0,0szNewFile db '.new.txt',0szErrOpenFile db '无法打开源文件!',0szErrCreateFile db '无法创建新的文本文件!',0szSuccess db '文件转换成功,新的文本文件保存为',0dh,0ah,'%s',0szSuccessCap db '提示' .code_FormatText proc uses esi _lpData,_dwSize,_hFile LOCAL @szBuffer[128]:byte,@dwBytesWrite mov esi,_lpData mov ecx,_dwSize lea edi,@szBuffer xor edx,edx cld_LoopBegin: or ecx,ecx jz _WriteLine lodsb dec ecx cmp al,0dh jz _LoopBegin cmp al,0ah jz _LineEnd stosb inc edx cmp edx,sizeof @szBuffer-2 jae _WriteLine jmp _LoopBegin_LineEnd: mov ax,0a0dh stosw inc edx inc edx_WriteLine: push ecx .if edx invoke WriteFile,_hFile,addr @szBuffer,edx,addr @dwBytesWrite,NULL .endif lea edi,@szBuffer ;上面代码中已经将@szBuffer的地址传递给edi在这里再传一次还有必要么? xor edx,edx pop ecx or ecx,ecx jnz _LoopBegin ret_FormatText endp_ProcFile proc LOCAL @hFile,@hFileNew,@dwBytesRead LOCAL @szNewFile[MAX_PATH]:byte LOCAL @szReadBuffer[512]:byte invoke CreateFile,addr szFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0 ;打开 .if eax == INVALID_HANDLE_VALUE invoke MessageBox,hWinMain,addr szErrOpenFile,NULL,MB_OK or MB_ICONEXCLAMATION ret .endif mov @hFile,eax invoke lstrcpy,addr @szNewFile,addr szFileName invoke lstrcat,addr @szNewFile,addr szNewFile invoke CreateFile,addr @szNewFile,GENERIC_WRITE,FILE_SHARE_READ,0,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,0 ;创建 .if eax == INVALID_HANDLE_VALUE invoke MessageBox,hWinMain,addr szErrCreateFile,NULL,MB_OK or MB_ICONEXCLAMATION invoke CloseHandle,@hFile ret .endif mov @hFileNew,eax xor eax,eax mov @dwBytesRead,eax .while TRUE lea esi,@szReadBuffer invoke ReadFile,@hFile,esi,sizeof @szReadBuffer,addr @dwBytesRead,0 .break .if ! @dwBytesRead invoke _FormatText,esi,@dwBytesRead,@hFileNew .endw invoke CloseHandle,@hFile invoke CloseHandle,@hFileNew invoke wsprintf,addr @szReadBuffer,addr szSuccess,addr @szNewFile invoke MessageBox,hWinMain,addr @szReadBuffer,addr szSuccessCap,MB_OK ret_ProcFile endp_ProcDlgMain proc uses ebx edi esi hWnd,wMsg,wParam,lParam LOCAL @stOpenFileName:OPENFILENAME mov eax,wMsg .if eax == WM_CLOSE invoke EndDialog,hWnd,NULL .elseif eax == WM_INITDIALOG push hWnd pop hWinMain invoke LoadIcon,hInstance,IDI_ICON1 invoke SendMessage,hWnd,WM_SETICON,ICON_BIG,eax invoke SendDlgItemMessage,hWnd,IDC_FILE,EM_SETLIMITTEXT,MAX_PATH,0 .elseif eax == WM_COMMAND mov eax,wParam .if ax == IDC_BROWSE invoke RtlZeroMemory,addr @stOpenFileName,sizeof OPENFILENAME mov @stOpenFileName.lStructSize,sizeof @stOpenFileName mov @stOpenFileName.Flags,OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST push hWinMain pop @stOpenFileName.hwndOwner mov @stOpenFileName.lpstrFilter,offset szFileExt mov @stOpenFileName.lpstrFile,offset szFileName mov @stOpenFileName.nMaxFile,MAX_PATH invoke GetOpenFileName,addr @stOpenFileName .if eax invoke SetDlgItemText,hWnd,IDC_FILE,addr szFileName .endif .elseif ax == IDC_FILE invoke GetDlgItemText,hWnd,IDC_FILE,addr szFileName,MAX_PATH mov ebx,eax invoke GetDlgItem,hWnd,IDOK invoke EnableWindow,eax,ebx .elseif ax == IDOK call _ProcFile .endif .else mov eax,FALSE ret .endif mov eax,TRUE ret_ProcDlgMain endpstart: invoke GetModuleHandle,NULL mov hInstance,eax invoke DialogBoxParam,hInstance,IDD_DIALOG1,NULL,offset _ProcDlgMain,NULL invoke ExitProcess,NULL end start
这次程序中使用的API函数和一些结构在以前的文章中都做过总结,没有出现新的内容,不在赘述,有某些不熟悉的,请查看以前的文章中的API函数和结构的信息的 详细描述。
本次程序分析到此结束。
- win32汇编 实现UNIX文件格式转换WINDOWS文件格式 的功能
- windows与unix文件格式转换
- 标注文件格式转换功能的简单实现
- Windows/DOS与Unix文件格式之间的相互转换
- DOS/Windows和Linux/Unix间的文件格式转换
- DOS/Windows和Linux/Unix间的文件格式转换
- DOS/Windows和Linux/Unix间的文件格式转换
- DOS/Windows和Linux/Unix间的文件格式转换
- 用sed转换Unix/Windows文件格式
- DOS文件格式转换成unix文件格式
- dos文件格式转换为Unix文件格式
- dos文件格式转换为Unix文件格式
- DOS/Windows和Linux/Unix间文件格式转换
- DOS/Windows和Linux/Unix间文件格式转换
- Windows & Unix 文件格式差异及win2unix转换脚本
- DOS/Windows和Linux/Unix间文件格式和字符集转换
- window和unix文件格式转换
- dos和unix文件格式转换
- iOS学习之—— UICollectionViewFlowLayout
- java.util.Date、java.sql.Date、java.sql.Time、java.sql.Timestamp区别和总结
- android intent
- html pre预格式文本是啥意思
- 虚拟专用网VPN
- win32汇编 实现UNIX文件格式转换WINDOWS文件格式 的功能
- ubuntu下samba服务器配置及常见问题解决
- maven私仓之发布公共类库
- 阿里云服务器怎么用?阿里云服务器使用教程
- Linux下的CentOS、Ubuntu、Gentoo 比较
- iPad、iPhone、Android 横屏、竖屏(window.orientation实现)的知识点
- OC混编swift时EMBEDDED_CONTENT_CONTAINS_SWIFT错误的处理
- JSON的哲学思维
- 转载:一个故事告诉你比特币的原理及运作机制