Не обрабатывает данные с файла - Assembler
Формулировка задачи:
Не линкуется выдает ошибки в чем проблема?
теперь выскакивают две ошибки
error A2070: invalid instruction operands
.386 ; 32-битный режим .model flat, stdcall ; компиляция в exe-файл с возможностью вызова API option casemap :none ; неразличение прописных и строчных символов ; содержит значения констант include C:\masm32\include\windows.inc ; STD_INPUT_HANDLE, ; STD_OUTPUT_HANDLE include <\masm32\include\kernel32.inc> include <\masm32\include\user32.inc> includelib <\masm32\lib\kernel32.lib> includelib <\masm32\lib\user32.lib> .const MEMSIZE equ 65535 .data ; сегмент данных hfile_write dd ? hfile_read dd ? buff_file db 0 file_read db "file_read.txt",0 file_write db "file_write.txt",0 file_read_size dd ? ;размер файла size_file_read dd ? ;количество считанных байт ByteWritten dd ? hConsoleInput DWORD ? ; переменные для хранения хэндлов ввода и вывода, hConsoleOutput DWORD ? ; названия этих переменных могут быть другими ; буфер 1 байт (со значением 0) Buffer byte 1 dup (0) ; для вода с клавиатуры 1 символа, ; название буфера может быть другим NumberOfCharsRead DWORD ? ; переменные для записи числа фактически NumberOfCharsWritten DWORD ? ; введенных и выведенных символов, ; названия этих переменных могут быть другими hMemory HANDLE ? pMemory DWORD ? msg1 byte "Задача выполненна успешно!" ; строковая переменная ; строковая переменная msg2 byte "Нажмите Enter, чтобы выйти...", 0 ; заканчивается нулем, ; так как она будет передана ; API-функции CharToOem msg1310 byte 13, 10 ; перевод строки ERROR_CreateFile byte "ERROR_CreateFile",0 ERROR_GetFileSize byte "ERROR_GetFileSize",0 ERROR_VirtualAlloc byte "ERROR_VirtualAlloc",0 ERROR_ReadFile byte "ERROR_ReadFile",0 ERROR_WriteFile byte "ERROR_WriteFile",0 .code ; сегмент кода start: invoke CreateFile, ADDR file_write, GENERIC_WRITE or GENERIC_READ, FILE_SHARE_WRITE or FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ;CMP EAX,-1 ;JE _ERROR_CreateFile mov hfile_write, eax invoke CreateFile, ADDR file_read, ;открываем файл для чтения для получения дискриптора файла GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL ;CMP EAX,-1 ;JE _ERROR_CreateFile mov hfile_read, eax invoke GetFileSize, hfile_read, NULL ;получаем размер файла ;CMP EAX,0 ;JE _ERROR_GetFileSize mov file_read_size,eax invoke GlobalAlloc,GMEM_MOVEABLE or GMEM_ZEROINIT,MEMSIZE mov hMemory,eax ;функция возвращает хэндл на запрошенный блок памяти invoke GlobalLock,hMemory mov pMemory,eax ;возвращает указатель на блок памяти invoke ReadFile, hfile_read, ;считываем данные с файла pMemory, ;Адрес буфера file_read_size, ;MEMSIZE-1, ;Размер буфера или сколько байтов нужно прочитать ADDR size_file_read, ; Адрес переменной, в которую записывается реальное количество прочитанных данных NULL ;CMP EAX,0 ;JE _ERROR_ReadFile ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov cx,file_read_size mov si,pMemory loop1: mov al,byte ptr[si] cmp al,'а' jl loop2 sub al,'а'-'a' mov byte ptr [si],al loop2: inc si loop loop1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; invoke WriteFile, hfile_write, pMemory, ; Указатель на буфер, содержащий данные, которые будут записаны в файл size_file_read, ; Число байтов, которые будут записаны в файл ADDR size_file_read,;ADDR ByteWritten, ;Указатель на переменную, которая получает число записанных байтов NULL ;CMP EAX,0 ;JE _ERROR_WriteFile invoke CloseHandle, hfile_read invoke CloseHandle, hfile_write invoke GlobalUnlock,pMemory invoke GlobalFree,hMemory invoke AllocConsole ; запрашиваем у Windows консоль invoke GetStdHandle, STD_INPUT_HANDLE ; получаем хэндл консоли для ввода mov hConsoleInput, EAX ; записываем хэндл в переменную invoke GetStdHandle, STD_OUTPUT_HANDLE ; получаем хэндл консоли для вывода mov hConsoleOutput, EAX ; записываем хэндл в переменную invoke WriteConsoleA, ; переводим строку в консоли hConsoleOutput, ; хэндл вывода ADDR msg1310, ; адрес строки msg1310 SIZEOF msg1310, ; размер строки msg1310 ADDR NumberOfCharsWritten, ; сюда функция запишет число символов 0 ; lpReserved передаем, как ноль invoke CharToOem, ADDR msg1, ADDR msg1 invoke WriteConsoleA, ; пишем " Hello, World!" hConsoleOutput, ADDR msg1, SIZEOF msg1, ADDR NumberOfCharsWritten, 0 invoke WriteConsoleA, ; переводим строку hConsoleOutput, ADDR msg1310, SIZEOF msg1310, ADDR NumberOfCharsWritten, 0 ;invoke CharToOem, ADDR msg2, ADDR msg2 ; перекодируем Win1251 -> DOS invoke WriteConsoleA, ; пишем " Нажмите Enter, чтобы выйти..." hConsoleOutput, ADDR msg2, (SIZEOF msg2) - 1, ; уменьшаем размер строки msg2 на 1 (из-за нуля) ADDR NumberOfCharsWritten, 0 invoke ReadConsoleA, ; ожидаем ввода в консоль hConsoleInput, ; хэндл ввода ADDR Buffer, ; адрес буфера 1, ; вводим 1 символ ADDR NumberOfCharsRead, ; сюда функция запишет число символов 0 ; lpReserved передаем, как ноль invoke ExitProcess, 0 ; сообщаем системе, что программа окончена end start ; завершает сегмент кода
Заменил на
mov ecx,file_read_size mov esi,pMemory loop1: mov eax,byte ptr[esi] ;error A2070: invalid instruction operands cmp eax,'а' jl loop2 sub eax,'а'-'a' mov byte ptr [esi],eax ;error A2070: invalid instruction operands loop2: inc esi loop loop1
Решение задачи: «Не обрабатывает данные с файла»
textual
Листинг программы
;cons4.asm .586P ;плоская модель памяти .MODEL FLAT, stdcall ;константы STD_OUTPUT_HANDLE equ -11 STD_INPUT_HANDLE equ -10 TIME_PERIODIC equ 1 ; тип вызова таймера ;атрибуты цветов FOREGROUND_BLUE equ 1h ; синий цвет букв FOREGROUND_GREEN equ 2h ; зеленый цвет букв FOREGROUND_RED equ 4h ; красный цвет букв FOREGROUND_INTENSITY equ 8h ; повышенная интенсивность BACKGROUND_BLUE equ 10h ; синий свет фона BACKGROUND_GREEN equ 20h ; зеленый цвет фона BACKGROUND_RED equ 40h ; красный цвет фона BACKGROUND_INTENSITY equ 80h ; повышенная интенсивность COL1 = 2h+8h ; цвет выводимого текста ;прототипы внешних процедур EXTERN wsprintfA:NEAR EXTERN GetStdHandle@4:NEAR EXTERN WriteConsoleA@20:NEAR EXTERN SetConsoleCursorPosition@8:NEAR EXTERN SetConsoleTitleA@4:NEAR EXTERN FreeConsole@0:NEAR EXTERN AllocConsole@0:NEAR EXTERN CharToOemA@8:NEAR EXTERN SetConsoleCursorPosition@8:NEAR 210 Часть II. Простые программы, консольные приложения, обработка файлов EXTERN SetConsoleTextAttribute@8:NEAR EXTERN ReadConsoleA@20:NEAR EXTERN timeSetEvent@20:NEAR EXTERN timeKillEvent@4:NEAR EXTERN ExitProcess@4:NEAR ;директивы компоновщику для подключения библиотек includelib c:\masm32\lib\user32.lib includelib c:\masm32\lib\kernel32.lib includelib c:\masm32\lib\winmm.lib ;----------------------------------------------- COOR STRUC X WORD ? Y WORD ? COOR ENDS ;сегмент данных _DATA SEGMENT HANDL DWORD ? HANDL1 DWORD ? STR2 DB "Пример таймера в консольном приложении",0 STR3 DB 100 dup(0) FORM DB "Число вызовов таймера: %lu",0 BUF DB 200 dup(?) NUM DWORD 0 LENS DWORD ? ; количество выведенных символов CRD COOR <?> ID DWORD ? ; идентификатор таймера HWND DWORD ? _DATA ENDS ;сегмент кода _TEXT SEGMENT START: ;перекодировать строку STR2 PUSH OFFSET STR2 PUSH OFFSET STR2 CALL CharToOemA@8 ;образовать консоль ;вначале освободить уже существующую CALL FreeConsole@0 CALL AllocConsole@0 ;получить HANDL1 ввода PUSH STD_INPUT_HANDLE CALL GetStdHandle@4 MOV HANDL1,EAX ;получить HANDL вывода PUSH STD_OUTPUT_HANDLE Глава 2.3. Консольные приложения 211 CALL GetStdHandle@4 MOV HANDL,EAX ;задать заголовок окна консоли PUSH OFFSET STR2 CALL SetConsoleTitleA@4 ;задать цветовые атрибуты выводимого текста PUSH COL1 PUSH HANDL CALL SetConsoleTextAttribute@8 ;установить таймер PUSH TIME_PERIODIC ; периодический вызов PUSH 0 PUSH OFFSET TIME ; вызываемая таймером процедура PUSH 0 ; точность вызова таймера PUSH 1000 ; вызов через одну секунду CALL timeSetEvent@20 MOV ID,EAX ;ждать ввод строки PUSH 0 PUSH OFFSET LENS PUSH 200 PUSH OFFSET BUF PUSH HANDL1 CALL ReadConsoleA@20 ;закрыть таймер PUSH ID CALL timeKillEvent@4 ;закрыть консоль CALL FreeConsole@0 PUSH 0 CALL ExitProcess@4 ;строка - [EBP+08H] ;длина в EBX LENSTR PROC ENTER 0,0 PUSH EAX PUSH EDI ;-------------------- CLD MOV EDI,DWORD PTR [EBP+08H] MOV EBX,EDI MOV ECX,100 ; ограничить длину строки XOR AL,AL REPNE SCASB ; найти символ 0 SUB EDI,EBX ; длина строки, включая 0 212 Часть II. Простые программы, консольные приложения, обработка файлов MOV EBX,EDI DEC EBX ;-------------------- POP EDI POP EAX LEAVE RET 4 LENSTR ENDP ;процедура вызывается таймером TIME PROC PUSHAD ; сохранить все регистры ;установить позицию курсора MOV CRD.X,0 MOV CRD.Y,10 PUSH CRD PUSH HANDL CALL SetConsoleCursorPosition@8 ;заполнить строку STR3 PUSH NUM PUSH OFFSET FORM PUSH OFFSET STR3 CALL wsprintfA ADD ESP,12 ; восстановить стек ;перекодировать строку STR3 PUSH OFFSET STR3 PUSH OFFSET STR3 CALL CharToOemA@8 ;вывести строку с номером вызова таймера PUSH OFFSET STR3 CALL LENSTR PUSH 0 PUSH OFFSET LENS PUSH EBX PUSH OFFSET STR3 PUSH HANDL CALL WriteConsoleA@20 INC NUM POPAD RET 20 ; выход с освобождением стека TIME ENDP _TEXT ENDS END START
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д