Консультация № 182387
05.03.2011, 00:17
73.71 руб.
0 5 1
Уважаемые эксперты, начал изучать исходник из учебника Зубкова и он показался интересным, но к сожалению он работает не так как надо.
Пожалуйста найдите ошибку для того чтобы первоначальное сообщение выводилось в нужной кодировке и самое главное не могу понять почему консоль исчезает и нет возможности пролистать содержимое файла.


Приложение:
;----------------------------------------------------------
;prg07_36.asm - Win32-консольное приложение для исследования порядка использования файлов, проецируемых в память.
;----------------------------------------------------------
.486
.model flat, STDCALL ;модель памяти flat
;STDCALL - передача параметров в стиле С (справа налево)
;вызываемая процедура чистит за собой стек
%NOINCL ;запретить вывод текста включаемых файлов
include WindowConA.inc
;Объявление внешними используемых в данной программе функций Win32 (ASCII):
extrn AllocConsole:PROC
extrn SetConsoleTitleA:PROC
extrn ExitProcess:PROC
extrn GetStdHandle:PROC
extrn CreateFileA:PROC
extrn CreateFileMappingA:PROC
extrn MapViewOfFile:PROC
extrn UnmapViewOfFile:PROC
extrn CloseHandle:PROC
extrn FlushFileBuffers:PROC
extrn FlushViewOfFile:PROC
extrn WriteFile:PROC
extrn SetConsoleCursorPosition:PROC
extrn ReadConsoleA:PROC
extrn WriteConsoleA:PROC
extrn GetFileSize:PROC
;макроопределения типов
SSHORT equ <dw 0>
;структура для установки положения курсора в консоли:
Coord struc
xx SSHORT
yy SSHORT
Coord ends
.data
TitleText db 'Пример использования отображенных в память файлов',0
NumWri dd 0
inFile db 80 dup (20)
con Coord <>
xxx dw 0
yyy dw 0
FileSize dd 0 ;размер файла
hinFile dd 0
hMapinFile dd 0
mes1 db 'Введите путь к исходному файлу:'
len_mes1=$-mes1
dOut dd 0
dIn dd 0
PointInRegion dd 0
.code
start proc near
;точка входа в программу:
;запрос консоли
call AllocConsole
;проверить успех запроса консоли
test ax, ax
jz exit ;неудача
;текст окна заголовка
push offset TitleText
call SetConsoleTitleA
;вывод строки текста
;вначале получим дескрипторы ввода и вывода консоли
push STD_OUTPUT_HANDLE
call GetStdHandle
mov dOut, eax ;dOut-дескриптор ввода вывода консоли
push STD_INPUT_HANDLE
call GetStdHandle
mov dIn, eax ;dIn-дескриптор ввода вывода консоли
;установим курсор в позицию (2, 5)
mov con.xx, 2
mov con.yy, 5
push con
push dOut
call SetConsoleCursorPosition
cmp eax, 0
jz exit ;если неуспех
;вывести приглашение на ввод имени исходного файла
push 0
push offset NumWri
push len_mes1
push offset mes1
push dOut
call WriteConsoleA
;установим курсор в позицию (2, 6)
mov con.xx, 2
mov con.yy, 6
push con
push dOut
call SetConsoleCursorPosition
cmp eax, 0
jz exit ;если неуспех
push 0
push offset NumWri
push 80
push offset inFile
push dIn
call ReadConsoleA ;читаем имя входного файла
lea eax, inFile
sub NumWri, 2
add eax, NumWri
mov [eax], byte ptr 0 ;сформировали ASCIIZ-строку
;------------------ inFile -----------------------------------------------------
;открытие объекта ядра "файл" для исходного файла inFile
push NULL
push FILE_ATTRIBUTE_NORMAL
push OPEN_ALWAYS
push NULL
push 0
push GENERIC_READ+GENERIC_WRITE ;разрешено чтение и запись в файл
push offset inFile
call CreateFileA
;проверить успех
cmp eax, 0ffffffffh
jz exit ;неудача
mov hinFile, eax
;создание объекта ядра "проецируемый файл" для исходного файла inFile
push NULL
push 0 ;размер файла - текущий
push 0
push PAGE_READWRITE
push NULL
push hinFile
call CreateFileMappingA
;проверить успех
cmp eax, 0
jz exit ;неудача
mov hMapinFile, eax
;проецирование файловых данных для исходного файла inFile на адресное пространство процесса
push NULL
push 0 ;смещение первого считываемого байта в файле
push 0
push FILE_MAP_WRITE
push hMapinFile
call MapViewOfFile
;проверить успех открытия файла
cmp eax, 0
jz exit ;неудача
mov PointInRegion, eax
mov ebx, eax ;адрес начала исходного файла в памяти в ebx
;------------------ inFile -----------------------------------------------------
;определим размер файла
;DWORD GetFileSize(HANDLE hFile,LPDWORD lpFileSizeHigh);
push 0
push hinFile
call GetFileSize
cmp eax,0
jz exit ;если неуспех
mov FileSize,eax ;сохраним размер файла
;------------------------------------------------------------------------------
;вывод на экран
;установим курсор в начальную позиция (0,0))
cycl:
mov ax,xxx
mov con.xx,ax
mov ax,yyy
mov con.yy,ax
push con
push dOut
call SetConsoleCursorPosition
cmp eax,0
jz exit ;если неуспех
;------------------- WriteConsoleA----------------------------------------
push 0 ;зарезервирован
push offset NumWri ;действительное количество выведенных символов
push FileSize ;длина выводимой строки (для простоты равна длине файла)
push PointInRegion ;указатель на начало выводимой строки в отображении файла
push dOut
call WriteConsoleA
cmp eax,0
; jz exit ;если неуспех - можно не делать, так как все равно закрывать объекты ядра
;------------------------------------------------------------------------
;разрываем связь файла на диске и его отображения
push NULL
push PointInRegion
call FlushViewOfFile
;закрываем объекты ядра "проекция файла" и "файл"
push hinFile
call CloseHandle
push hMapinFile
call CloseHandle
;выход из приложения
exit:
;готовим вызов VOID ExitProcess(UINT uExitCode)
push 0
call ExitProcess
start endp
end start

Обсуждение

давно
Посетитель
7438
7205
06.03.2011, 03:53
общий
это ответ
Здравствуйте, ANATOLY FIRST!
1) Кодировка.
Не секрет, что консольные программы работают в кодировке OEM (т.е. ASCII), а все наши строки заданы в ANSI.
Что делать? Можно предложить, как минимум, два простых способа:
Первый: элементарно перекодировать исходный код программы в ASCII (Почему бы и нет? Дешево и сердито)
Второй: предварительная перекодировка строк из ANSI в ASCII при помощи функции CharToOem

2) Почему изчезает консоль? А чего Вы ожидали? Программа все сделала, завершилась, ОС завершила консоль... Так и должно быть...
Как побороть? Это сделать не просто, а очень просто!Надо просто перед выходом подождать чего-то с клавиатуры.
Можно делать по-разному. Я в программе использовал дополнительный ввод строки. Т.о., выход из программы будет по нажатию на Enter.
До нажатия на Enter можно подвигать содержимое консоли при помощи полосы прокрутки...
Программу слегка подправил под masm. Мне так больше нравится
Удачи в освоении ассемблера!
[code h=200];----------------------------------------------------------
;prg07_36.asm - Win32-консольное приложение для исследования порядка использования файлов, проецируемых в память.
;----------------------------------------------------------
.486
.model flat, STDCALL ;модель памяти flat
;STDCALL - передача параметров в стиле С (справа налево)
;вызываемая процедура чистит за собой стек
;%NOINCL ;запретить вывод текста включаемых файлов
;include WindowConA.inc
include c:\masm32\include\windows.inc
include c:\masm32\include\kernel32.inc
include c:\masm32\include\user32.inc

includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib

;Объявление внешними используемых в данной программе функций Win32 (ASCII):
;extrn AllocConsole:PROC
;extrn SetConsoleTitleA:PROC
;extrn ExitProcess:PROC
;extrn GetStdHandle:PROC
;extrn CreateFileA:PROC
;extrn CreateFileMappingA:PROC
;extrn MapViewOfFile:PROC
;extrn UnmapViewOfFile:PROC
;extrn CloseHandle:PROC
;extrn FlushFileBuffers:PROC
;extrn FlushViewOfFile:PROC
;extrn WriteFile:PROC
;extrn SetConsoleCursorPosition:PROC
;extrn ReadConsoleA:PROC
;extrn WriteConsoleA:PROC
;extrn GetFileSize:PROC
;макроопределения типов
SSHORT equ <dw 0>
;структура для установки положения курсора в консоли:
Coord struc
xx SSHORT
yy SSHORT
Coord ends
.data
TitleText db 'Пример использования отображенных в память файлов',0
NumWri dd 0
inFile db 80 dup (20)
con Coord <>
xxx dw 0
yyy dw 0
FileSize dd 0 ;размер файла
hinFile dd 0
hMapinFile dd 0
mes1 db 'Введите путь к исходному файлу:',0
len_mes1=$-mes1-1 ;-1, чтобы убрать 0
dOut dd 0
dIn dd 0
PointInRegion dd 0
.code
start proc near
;точка входа в программу:
;запрос консоли
invoke AllocConsole
;проверить успех запроса консоли
test ax, ax
jz exit ;неудача

;текст окна заголовка
;сначала преобразуем из ANSI в ASCII
invoke CharToOem, addr TitleText, addr TitleText
;зададим заголовок окна
invoke SetConsoleTitleA, addr TitleText

;вывод строки текста
;вначале получим дескрипторы ввода и вывода консоли
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov dOut, eax ;dOut-дескриптор ввода вывода консоли
invoke GetStdHandle, STD_INPUT_HANDLE
mov dIn, eax ;dIn-дескриптор ввода вывода консоли

;установим курсор в позицию (2, 5)
mov con.xx, 2
mov con.yy, 5
invoke SetConsoleCursorPosition, dOut, dword ptr con
cmp eax, 0
jz exit ;если неуспех

;вывести приглашение на ввод имени исходного файла
;сначала преобразуем из ANSI в ASCII
invoke CharToOem, addr mes1, addr mes1
;выводим
invoke WriteConsoleA, dOut, addr mes1, len_mes1, addr NumWri, 0

;установим курсор в позицию (2, 6)
mov con.xx, 2
mov con.yy, 6
invoke SetConsoleCursorPosition, dOut, dword ptr con
cmp eax, 0
jz exit ;если неуспех

;читаем имя входного файла
invoke ReadConsoleA, dIn, addr inFile, 80, addr NumWri, 0

;сформировали ASCIIZ-строку
lea eax, inFile
add eax, NumWri
mov byte ptr [eax-2], 0

;------------------ inFile -----------------------------------------------------
;открытие объекта ядра "файл" для исходного файла inFile
invoke CreateFileA, addr inFile, GENERIC_READ+GENERIC_WRITE, 0, NULL, \
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL
;проверить успех
cmp eax, 0ffffffffh
jz exit ;неудача
mov hinFile, eax

;создание объекта ядра "проецируемый файл" для исходного файла inFile
invoke CreateFileMappingA, hinFile, NULL, PAGE_READWRITE, 0, 0, NULL
;проверить успех
cmp eax, 0
jz exit ;неудача
mov hMapinFile, eax

;проецирование файловых данных для исходного файла inFile на адресное пространство процесса
invoke MapViewOfFile, hMapinFile, FILE_MAP_WRITE, 0, 0, NULL
;проверить успех открытия файла
cmp eax, 0
jz exit ;неудача
mov PointInRegion, eax
mov ebx, eax ;адрес начала исходного файла в памяти в ebx

;------------------ inFile -----------------------------------------------------
;определим размер файла
;DWORD GetFileSize(HANDLE hFile,LPDWORD lpFileSizeHigh);
invoke GetFileSize, hinFile, 0
cmp eax,0
jz exit ;если неуспех
mov FileSize,eax ;сохраним размер файла

;------------------------------------------------------------------------------
;вывод на экран
;установим курсор в начальную позиция (0,0))
cycl:
mov ax,xxx
mov con.xx,ax
mov ax,yyy
mov con.yy,ax
invoke SetConsoleCursorPosition, dOut, dword ptr con
cmp eax,0
jz exit ;если неуспех

;------------------- WriteConsoleA----------------------------------------
invoke WriteConsoleA, dOut, PointInRegion, FileSize, addr NumWri, 0

;ждем ввод чего-нибудь, чтобы окно консоли сразу не закрылось !
invoke ReadConsoleA, dIn, addr inFile, 80, addr NumWri, 0

; cmp eax,0
; jz exit ;если неуспех - можно не делать, так как все равно закрывать объекты ядра

;------------------------------------------------------------------------
;разрываем связь файла на диске и его отображения
invoke FlushViewOfFile, PointInRegion, NULL

;закрываем объекты ядра "проекция файла" и "файл"
invoke CloseHandle, hinFile
invoke CloseHandle, hMapinFile
;выход из приложения
exit:
;VOID ExitProcess(UINT uExitCode)
invoke ExitProcess, 0
start endp
end start
[/code]
5
Спасибо;)
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
06.03.2011, 18:34
общий
Адресаты:
Установил масм10, попытался откомпилировать Ваш исходник и вылезла такая бяка.
Не подскажите в чем дело?
Прикрепленные файлы:
b5086a146cfb76b6bdcb014159bf6f4f.jpg
давно
Посетитель
7438
7205
06.03.2011, 22:52
общий
Тяжело сказать... Какой-то конфликт...
Дайте мне ссылку, по которой скачали masm, посмотрю.

В принципе, можете подправить свою программу... Просмотрите и найдете, что и как надо сделать...
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
07.03.2011, 17:17
общий
Адресаты:
Ссылка первая в гугле: http://www.masm32.com/masmdl.htm, на виртуальной машине такая же ошибка, все остальные примеры\проекты компилируется на ура. Поэтому подправил тасм исходник. Жаль что таким алгоритмом нельзя просматривать файлы больше 6-12кб.
Тем не менее благодарю за внимание
давно
Посетитель
7438
7205
07.03.2011, 18:05
общий
Очень странно, у меня masm прекрасно работает...
Могу дать свой makeit.bat для компиляции...
[code h=200]@echo off
:source file name
set n=prg07_36
: -------------------------------
: if resources exist, build them
: -------------------------------
if not exist rsrc.rc goto over1
\MASM32\BIN\Rc.exe /v /x rsrc.rc
\MASM32\BIN\Cvtres.exe /machine:ix86 rsrc.res
:over1

if exist %n%.obj del %n%.obj
if exist %n%.exe del %n%.exe

: -----------------------------------------
: assemble asm into an OBJ file
: -----------------------------------------
\MASM32\BIN\Ml.exe /c /Cp /Fl /coff /Ic:\masm32\include %n%.asm
if errorlevel 1 goto errasm

if not exist rsrc.obj goto nores

: --------------------------------------------------
: link the main OBJ file with the resource OBJ file
: --------------------------------------------------
\MASM32\BIN\Link.exe /SUBSYSTEM:WINDOWS /libpath:c:\masm32\lib %n%.obj rsrc.obj
if errorlevel 1 goto errlink
dir %n%.*
goto TheEnd

:nores
: -----------------------
: link the main OBJ file
: -----------------------
\MASM32\BIN\Link.exe /SUBSYSTEM:WINDOWS /libpath:c:\masm32\lib %n%.obj
if errorlevel 1 goto errlink
dir %n%.*
goto TheEnd

:errlink
: ----------------------------------------------------
: display message if there is an error during linking
: ----------------------------------------------------
echo.
echo There has been an error while linking this project.
echo.
goto TheEnd

:errasm
: -----------------------------------------------------
: display message if there is an error during assembly
: -----------------------------------------------------
echo.
echo There has been an error while assembling this project.
echo.
goto TheEnd

:TheEnd

pause
[/code]
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Форма ответа