初学汇编,编译出错求助
正在看《windows环境下32位汇编语言程序设计》,第350页的小程序FormatText,看到ReadFile函数只能一次读取指定个数字符,
想换成一次读取一行的函数,网上找到些代码,替换后编译出错,
错误信息:
Microsoft (R) Program Maintenance Utility Version 8.00.50727.762
Copyright (C) Microsoft Corporation. All rights reserved.
ml /c /coff FormatText.asm
Microsoft (R) Macro Assembler Version 6.14.8444
Copyright (C) Microsoft Corp 1981-1997. All rights reserved.
Assembling: FormatText.asm
FormatText.asm(136) : error A2155: cannot use 16-bit register with a 32-bit addr
ess
NMAKE : fatal error U1077: 'D:\masm32\bin\ml.EXE' : return code '0x1'
Stop.
红色部分为自定义的函数,求解
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Sample code for < Win32ASM Programming 2nd Edition>
; by 罗云彬, http://asm.yeah.net
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; FormatText.asm
; 文件读写例子 —— 将 Unix 格式的文本文件(以0ah换行)转换成 PC 格式
; 的文本文件(以0dh,0ah换行),读写文件操作使用文件操作函数。
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 使用 nmake 或下列命令进行编译和链接:
; ml /c /coff FormatText.asm
; rc FormatText.rc
; Link /subsystem:windows FormatText.obj FormatText.res
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386
.model flat, stdcall
option casemap :none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
includewindows.inc
includeuser32.inc
includelibuser32.lib
includekernel32.inc
includelibkernel32.lib
includecomdlg32.inc
includelibcomdlg32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Equ 等值定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ICO_MAINequ1000
DLG_MAINequ100
IDC_FILEequ101
IDC_BROWSEequ102
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data?
hInstancedd?
hWinMaindd?
szFileNamedbMAX_PATH dup (?)
.const
szFileExtdb'文本文件',0,'*.txt',0,0
szNewFiledb'.new.txt',0
szErrOpenFiledb'无法打开源文件!',0
szErrCreateFiledb'无法创建新的文本文件!',0
szSucceesdb'文件转换成功,新的文本文件保存为',0dh,0ah,'%s',0
szSucceesCapdb'提示',0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 在缓冲区中找出一行数据,处理换行并保存
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_FormatTextprocuses esi _lpData,_dwSize,_hFile
local@szBuffer[128]:byte,@dwBytesWrite
movesi,_lpData
movecx,_dwSize
leaedi,@szBuffer
xoredx,edx
cld
_LoopBegin:
orecx,ecx
jz_WriteLine
lodsb
dececx
cmpal,0dh;遇到0dh则丢弃
jz_LoopBegin
cmpal,0ah;遇到0ah则扩展为0dh,0ah
jz_LineEnd
stosb
incedx
cmpedx,sizeof @szBuffer-2
jae_WriteLine;行缓冲区满则保存
jmp_LoopBegin
_LineEnd:
movax,0a0dh
stosw
incedx
incedx
_WriteLine:
pushecx
.ifedx
invokeWriteFile,_hFile,addr @szBuffer,edx,addr @dwBytesWrite,NULL
.endif
leaedi,@szBuffer
xoredx,edx
popecx
orecx,ecx
jnz_LoopBegin
ret
_FormatTextendp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;读取文件中的一行数据到缓冲区
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ReadLine proc hFile, cBuf, ccSize
local @iRead
pushf
push ebx
push ecx
push edx
push esi
mov @iRead, 0
cld
mov edx, cBuf
mov esi, edx
mov ebx, hFile
l_read1:
mov ah, 3fh
mov cx, 1
int 21h ; 读入一个字符
jc l_ret ; 读入出错的话, 直接返回
lodsb
cmp al, 0dh ; 是回车?
je l_0d
cmp al, 0ah ; 是换行
je l_0a
inc edx
inc @iRead
jmp l_read1 ; 不是,转去读入下一字符
l_0d:
mov ah, 3fh
mov cx, 1
int 21h ; 刚才是回车, 再读入下一字符
jc l_ret
cmp byte ptr [si][-1], 0ah ; 看看是否是换行
je l_ret
mov ax, 4201h
mov cx, -1 ; 如果不是换行, 文件指针回退一, 即将刚才那个字符返给文件里
mov dx, cx
int 21h
jmp l_ret
l_0a:
l_ret:
pop esi
pop edx
pop ecx
pop ebx
popf
mov eax, @iRead
ret
_ReadLine endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcFileproc
local@hFile,@hFileNew,@dwBytesRead
local@szNewFile[MAX_PATH]:byte
local@szReadBuffer[512]:byte
;********************************************************************
; 打开文件
;********************************************************************
invokeCreateFile,addr szFileName,GENERIC_READ,FILE_SHARE_READ,0,\
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0
.ifeax ==INVALID_HANDLE_VALUE
invokeMessageBox,hWinMain,addr szErrOpenFile,NULL,MB_OK or MB_ICONEXCLAMATION
ret
.endif
mov@hFile,eax
;********************************************************************
; 创建输出文件
;********************************************************************
invokelstrcpy,addr @szNewFile,addr szFileName
invokelstrcat,addr @szNewFile,addr szNewFile
invokeCreateFile,addr @szNewFile,GENERIC_WRITE,FILE_SHARE_READ,\
0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0
.ifeax ==INVALID_HANDLE_VALUE
invokeMessageBox,hWinMain,addr szErrCreateFile,NULL,MB_OK or MB_ICONEXCLAMATION
invokeCloseHandle,@hFile
ret
.endif
mov@hFileNew,eax
;********************************************************************
; 循环读出文件并处理每个字节
;********************************************************************
xoreax,eax
mov@dwBytesRead,eax
.whileTRUE
leaesi,@szReadBuffer
;invokeReadFile,@hFile,esi,sizeof @szReadBuffer,addr @dwBytesRead,0
;************************************************************************
;自定义函数
;************************************************************************
invoke_ReadLine,@hFile,esi,sizeof @szReadBuffer
mov@dwBytesRead,eax
;************************************************************************
.break.if ! @dwBytesRead
invoke_FormatText,esi,@dwBytesRead,@hFileNew
.endw
invokeCloseHandle,@hFile
invokeCloseHandle,@hFileNew
invokewsprintf,addr @szReadBuffer,addr szSuccees,addr @szNewFile
invokeMessageBox,hWinMain,addr @szReadBuffer,addr szSucceesCap,MB_OK
ret
_ProcFileendp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcDlgMainprocuses ebx edi esi hWnd,wMsg,wParam,lParam
local@stOpenFileName:OPENFILENAME
moveax,wMsg
.ifeax ==WM_CLOSE
invokeEndDialog,hWnd,NULL
;********************************************************************
.elseifeax ==WM_INITDIALOG
pushhWnd
pophWinMain
invokeLoadIcon,hInstance,ICO_MAIN
invokeSendMessage,hWnd,WM_SETICON,ICON_BIG,eax
invokeSendDlgItemMessage,hWnd,IDC_FILE,EM_SETLIMITTEXT,MAX_PATH,0
;********************************************************************
.elseifeax ==WM_COMMAND
moveax,wParam
.ifax ==IDC_BROWSE
;********************************************************************
invokeRtlZeroMemory,addr @stOpenFileName,sizeof OPENFILENAME
mov@stOpenFileName.lStructSize,SIZEOF @stOpenFileName
mov@stOpenFileName.Flags,OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST
pushhWinMain
pop@stOpenFileName.hwndOwner
mov@stOpenFileName.lpstrFilter,offset szFileExt
mov@stOpenFileName.lpstrFile,offset szFileName
mov@stOpenFileName.nMaxFile,MAX_PATH
invokeGetOpenFileName,addr @stOpenFileName
.ifeax
invokeSetDlgItemText,hWnd,IDC_FILE,addr szFileName
.endif
;********************************************************************
.elseifax ==IDC_FILE
invokeGetDlgItemText,hWnd,IDC_FILE,addr szFileName,MAX_PATH
movebx,eax
invokeGetDlgItem,hWnd,IDOK
invokeEnableWindow,eax,ebx
;********************************************************************
.elseifax ==IDOK
call_ProcFile
.endif
;********************************************************************
.else
moveax,FALSE
ret
.endif
moveax,TRUE
ret
_ProcDlgMainendp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
invokeGetModuleHandle,NULL
movhInstance,eax
invokeDialogBoxParam,hInstance,DLG_MAIN,NULL,offset _ProcDlgMain,NULL
invokeExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
endstart
[解决办法]
cmp byte ptr [esi][-1], 0ah ; 看看是否是换行 编译能通过,不知道能不能正常运行。试试吧
[解决办法]
出错信息已经说的很明白了,在第136行,si是16位寄存器,而-1是32位地址偏移,所以编译出错了,向ls说的那样把si换成32位寄存器esi就可以编译了。