Форум программистов, компьютерный форум, киберфорум
Assembler: Windows/protected mode
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.60/15: Рейтинг темы: голосов - 15, средняя оценка - 4.60
11 / 10 / 2
Регистрация: 19.02.2018
Сообщений: 393
MASM

Длина строки, считанной из текстового файла

10.06.2020, 22:12. Показов 3235. Ответов 13
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Скажите, пожалуйста, правильно ли нахожу длину строки.
Если написать 2 символа получится 4, а если записать их в текстовый документ, что получится всего 2 байта.

Использую masm32

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
.data
cnt dd 0 ; количество символов выведенных в консоль.
hin dd 0 ; ввод.
fName db "simple.txt",0; имя файла.
buf   dd 255 dup (0)
.code
MAIN:
invoke GetStdHandle, -10; код ввода. получить хендл.
mov hin,eax; отправить в eax.
lea eax, cnt; отправить кол-во символов в eax.
lea ebx, buf ; отправить адрес строки в ebx.
invoke ReadConsoleA, hin, ebx, 255, eax, 0
invoke CloseHandle, hin; закрыть ввод.
mov edi,ebx
call _strlen
 
printf ("lean str = %d\n", eax)
  invoke  crt__getch; ждать нажатия.
  invoke ExitProcess, 0; вызов функции выхода, передаем 1 параметр 4 байта.
 
  _strlen:
  xor eax,eax
  @1:
  inc eax
  cmp byte ptr[eax+edi],0
  jnz @1
  ret
 
 _TEXT ENDS
 
END MAIN
Добавлено через 39 минут
так вроде работает
Assembler
1
2
3
4
5
6
7
8
9
10
11
invoke GetStdHandle, -10; код ввода. получить хендл.
mov hin,eax; отправить в eax.
lea eax, cnt; отправить кол-во символов в eax.
lea ebx, buf ; отправить адрес строки в ebx.
invoke ReadConsoleA, hin, ebx, 255, eax, 0
invoke CloseHandle, hin; закрыть ввод.
 
invoke lstrlen, ebx
sub eax, 2
mov cnt, eax 
printf ("lean str = %d\n", cnt)
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
10.06.2020, 22:12
Ответы с готовыми решениями:

Как создавать объекты на основе считанной инфы из текстового файла
Доброго времени суток, столкнулся с такой проблемой: Как создавать на основе считанных данных объект? Тут я узнал имя объекта и его...

Присвоить переменной значение, являющееся целой строкой, считанной из текстового файла
День добрый всем:) Есть небольшой код: for /f "UsebackQ skip=%a%" %%A IN ("keyPS.txt") do (set "keyPS=%%~A" && goto...

Извлечь из текстового файла строки, длина которых больше заданной
Добрый день. Прошу помощи так как в прологе полный 0. Поиск помог мне найти рабочий код от Грымзика из этой темы. Однако это...

13
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8644 / 4479 / 1669
Регистрация: 01.02.2015
Сообщений: 13,883
Записей в блоге: 11
11.06.2020, 14:19
Егор Щербанов, поделитесь описанием решения проблемы - просто из одного кода неясна ни сама суть вопроса ни способ решения проблемы.
0
11 / 10 / 2
Регистрация: 19.02.2018
Сообщений: 393
11.06.2020, 15:17  [ТС]
ФедосеевПавел, Хорошо, всё очень просто, открывается консоль, мы пишем текст, он записывается в текстовый файл, количество символов, которым мы ввели, равно количество байт записанных в файл.

Так всё работает, но с русскими символами получается какая-то абракадабра.
Регистр ebx хранит строку, скажите, пожалуйста, как записать строку из регистра в переменную?
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
.686P; директива процессора.
.model flat,stdcall; модель памяти, соглашение вызовов функции.
 
option casemap :none; заставляет компилятор языка ассемблера различать большие и маленькие буквы в метках и именах процедур.
 
include C:\masm32\include\kernel32.inc; импорт функции.
include C:\masm32\include\msvcrt.inc
include C:\masm32\include\windows.inc
 
includelib C:\masm32\lib\kernel32.lib; импорт библиотеки.
includelib C:\masm32\lib\msvcrt.lib
 
include C:\masm32\macros\macros.asm; для функции printf.
 
.data
cnt dd 0 ; количество символов выведенных в консоль.
hin dd 0 ; ввод.
fName db "simple.txt",0; имя файла.
buf   dd 255 dup (0)
.code
MAIN:
 
call input_consol; ввод в консоль, подсчет символов в строке.
call write_in_file; записать в файл.
call read_file; читать файл.
 
  invoke  crt__getch; ждать нажатия.
  invoke ExitProcess, 0; вызов функции выхода, передаем 1 параметр 4 байта.
 
read_file: ;
  invoke CreateFile, ebx, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0
  mov hin, eax; получить хендл файла.
  invoke GetFileSize, hin, 0;  размер файла.
  mov cnt, eax; сохранить размер файла.
  lea eax, [buf]; буфер.
  lea ebx, cnt; размер файла.
  invoke ReadFile, hin, ebx, cnt, eax, 0
   invoke CloseHandle, hin
  ret
 
write_in_file: ;
  push ebx
  lea ebx, [fName]; имя файла.
    invoke CreateFile, ebx, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, 0
    mov hin, eax; хендл файла.
    pop ebx; строку, кторотую ввели в консоль
    invoke WriteFile, hin, ebx, cnt, 0, 0;
    invoke CloseHandle, hin;
    printf ("lean str = %d\n", cnt)
  ret
 
  input_consol: ; ввод в консоль, подсчет символов в строке.
  invoke GetStdHandle, -10; код ввода. получить хендл.
  mov hin,eax; отправить в eax.
  lea eax, cnt; отправить кол-во символов в eax.
  lea ebx, buf ; отправить адрес строки в ebx.
  invoke ReadConsoleA, hin, ebx, 255, eax, 0
  push ebx
  invoke CloseHandle, hin; закрыть ввод.
  invoke lstrlen, ebx
  sub eax, 2
  mov cnt, eax ; количество символов в строке
  pop ebx
  ret
 
 _TEXT ENDS
 
END MAIN
0
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8644 / 4479 / 1669
Регистрация: 01.02.2015
Сообщений: 13,883
Записей в блоге: 11
11.06.2020, 16:06
Регистр ebx не может хранить строку, т.к. размер ebx - всего 4 байта.
Судя по всему - строка находится в буфере/массиве buf.
А значение ebx никто не обещал сохранять после вызова WinAPI.
0
11 / 10 / 2
Регистрация: 19.02.2018
Сообщений: 393
11.06.2020, 17:03  [ТС]
ФедосеевПавел, Простите пожалуйста, не так выразился, ebx содержит указатель на буфер строки, можно ли записать его в переменную?
0
780 / 412 / 75
Регистрация: 29.03.2013
Сообщений: 849
11.06.2020, 17:15
Цитата Сообщение от ФедосеевПавел Посмотреть сообщение
А значение ebx никто не обещал сохранять после вызова WinAPI
Тут цитата из asmintro.chm от masm32 (раздел Register Preservation Convention):
All of the Windows API functions are written this way and you can safely assume that any values you have in EBX ESI and EDI will be the same when the API function return to your calling code.
1
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8644 / 4479 / 1669
Регистрация: 01.02.2015
Сообщений: 13,883
Записей в блоге: 11
11.06.2020, 18:04
Особенность Windows в том, что по умолчанию для кириллицы используются разные кодировки в консольных и в GUI приложениях.
Перед записью перекодируйте в ANSI и тогда Блокнот откроет то, что вы набирали в консоли.

Вот мой вариант чтения строки с консоли и сохранения её в файл.
В строке 47 перекодировка.
Ошибки, при открытии и записи в файл, обрабатываю библиотечной процедурой GetErrDescription из masm32
https://www.cyberforum.ru/post14452061.html
Рекомендую и вам обрабатывать ошибки.
Здесь ошибку можно воспроизвести если перед запуском программы открыть выходной файл каким-нибудь редактором или просмотровщиком, блокирующим совместную работу.
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
.686
.model flat, stdcall
option casemap :none
 
        include \masm32\include\windows.inc
 
        include \masm32\include\user32.inc
        include \masm32\include\kernel32.inc
        include \masm32\include\masm32.inc
 
        includelib \masm32\lib\user32.lib
        includelib \masm32\lib\kernel32.lib
        includelib \masm32\lib\masm32.lib
.const
        szPrompt        db      0Dh, 0Ah, 'Enter a string:', 0Dh, 0Ah, 0
        szPressEnter    db      0Dh, 0Ah, 0Dh, 0Ah, 'Press ENTER to exit', 0
        aszFileName     db      'outfile.txt', 0
 
.data?
        hConsoleOutput  HANDLE  ?
        hConsoleInput   HANDLE  ?
        hFile           HANDLE  ?
        aBuffer         db      1024 dup(?)
        nBufLen         dd      ?
        temp            dd      ?
 
.code
 
main    proc
 
        ; получение описателей ввода и вывода консоли
        invoke  GetStdHandle,   STD_INPUT_HANDLE
        mov     hConsoleInput,  eax
        invoke  GetStdHandle,   STD_OUTPUT_HANDLE
        mov     hConsoleOutput, eax
        ;вввод исходных данных
        invoke  WriteConsole, hConsoleOutput, ADDR szPrompt,\   ;  Write('Input string : ');
                LENGTHOF szPrompt-1, ADDR nBufLen, NULL
        invoke  ReadConsole, hConsoleInput, ADDR aBuffer,\      ;readln(str);
                LENGTHOF aBuffer-1, ADDR nBufLen, NULL
        lea     esi,    [aBuffer]       ;удаление из буфера
        mov     eax,    [nBufLen]       ;символов перевода строки
        sub     eax,    2
        mov     [esi+eax],      byte ptr 0
        mov     [nBufLen],      eax
        ;для кириллицы выполним перекодировку OEM to ANSI
        invoke  OemToChar,      ADDR aBuffer, ADDR aBuffer
        ;обработка:
        invoke  CreateFile,     ADDR aszFileName,\      ;lpFileName
                                GENERIC_WRITE,\         ;dwDesiredAccess
                                NULL,\                  ;dwShareMode
                                NULL,\
                                CREATE_ALWAYS,\
                                FILE_ATTRIBUTE_NORMAL,\
                                NULL
        cmp     eax,    INVALID_HANDLE_VALUE
        jne     @f
                ;сообщение об ошибке открытия на запись
                invoke  GetErrDescription,      0
                jmp     @@Exit
        @@:
        mov     [hFile],        eax
 
        invoke  WriteFile,      [hFile], ADDR aBuffer, [nBufLen],
                ADDR temp, NULL
        test    eax,    eax
        jne     @f
                ;сообщение об ошибке при записи
                invoke  GetErrDescription,      0
                jmp     @f
        @@:
 
        invoke  CloseHandle,    [hFile]
@@Exit:
        ;ожидание нажатия ENTER
        invoke  WriteConsole, hConsoleOutput, ADDR szPressEnter,\
                LENGTHOF szPressEnter - 1, ADDR nBufLen, NULL
        invoke  ReadConsole, hConsoleInput, ADDR aBuffer,\
                LENGTHOF aBuffer-1, ADDR nBufLen, NULL
 
        invoke  ExitProcess, 0
main    endp
 
end     main
Добавлено через 10 минут
Argogo, согласен.
Помню, что какие-то регистры сохранятся, а какие-то - не сохранятся.
Помню, что столкнулся с особенностью invoke в masm - регистр eax используется для заполнения стека параметрами процедуры и поэтому, в eax не удастся корректно передать не крайний правый параметр
Assembler
1
2
mov eax, [var]
invoke myproc, param1, eax, param3, param4  ;в myproc в eax не будет передано значение [var] - это особенность invoke
Чтобы не заморачиваться с запоминанием этих особенностей - всё, что нужно для дальнейшей работы программы сохраняю в переменных, в стеке, но не собираюсь доверять чьим-то реализациям процедур.

Конечно, если потребуется экономия на каждом байте кода, на каждом лишнем замедлении при обращении к памяти, то буду вынужден помнить и применять все соглашения.

Добавлено через 7 минут
Цитата Сообщение от Егор Щербанов Посмотреть сообщение
Регистр ebx хранит строку, скажите, пожалуйста, как записать строку из регистра в переменную?
Не могу понять.
Вот в ebx указатель на строку. Строка и так в памяти, в переменной буфера чтения. Если нужно скопировать из буфера в другую переменную, в другой буфер, то
Assembler
1
2
3
4
5
6
7
lea esi, [aBuffer]
lea edi, [aNewString]
@@:
  lodsb
  stosb
  test al, al
jne @b
Это не очень оптимально. В masm32 есть процедура копирования по 4 байта за раз - она быстрее.
0
11 / 10 / 2
Регистрация: 19.02.2018
Сообщений: 393
11.06.2020, 23:41  [ТС]
Спасибо вам огромное за ваш ответ. Мне потребуется немного времени чтобы его досконально изучить.
Раньше программировал на python, там всё намного легче, но захотелось хардкора. Бросить вызов своему уму.

Как мы прочитали файл, можно вывести в консоль с помощью функции printf ("str = %s\n", ebx).

Никак не получается вывести в консоль.

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  lea ebx, [fName]; имя файла.
 
  invoke CreateFile, ebx, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0
  mov hin, eax; получить хендл файла.
  invoke GetFileSize, hin, 0;  размер файла.
  mov cnt, eax; сохранить размер файла.
  push cnt; отправить количество символов в стек.
  lea eax, [buf]; буфер.
  lea ebx, cnt; размер файла.
  invoke ReadFile, hin, ebx, cnt, eax, 0; указатель на строку находится в ebx.
 
  printf ("str = %s\n", ebx)
  invoke CloseHandle, hin
 
   invoke GetStdHandle, -11; код вывода.
   mov hin,eax; получить хендл файла.
   pop cnt
 
   printf ("len str = %d\n", cnt)
   invoke WriteConsoleA, hin, ADDR buf, cnt, 0, 0
   invoke CloseHandle, hin
Вот что получается на видео https://www.youtube.com/watch?... e=youtu.be
0
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8644 / 4479 / 1669
Регистрация: 01.02.2015
Сообщений: 13,883
Записей в блоге: 11
11.06.2020, 23:51
Мне кажется, что неправильный порядок параметров ReadFile
В моей программе (отсюда)
Assembler
1
2
        invoke  ReadFile,      hFile, ADDR Buffer, SIZEOF Buffer,\
                                ADDR dwBytesRead, NULL
В вашей программе
Assembler
1
2
3
  lea eax, [buf]; буфер.
  lea ebx, cnt; размер файла.
  invoke ReadFile, hin, ebx, cnt, eax, 0; указатель на строку находится в ebx.
0
11 / 10 / 2
Регистрация: 19.02.2018
Сообщений: 393
12.06.2020, 00:06  [ТС]
ФедосеевПавел,
Вы уделяете мне сколько своего времени, функция printf ("str = %s\n", ebx). Корректно всё выводит,
А функция WriteConsoleA, нет, хотя ebx указывает на буфер обмена.
Вот исходник

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
.686P; директива процессора.
.model flat,stdcall; модель памяти, соглашение вызовов функции.
 
option casemap :none; заставляет компилятор языка ассемблера различать большие и маленькие буквы в метках и именах процедур.
 
include C:\masm32\include\kernel32.inc; импорт функции.
include C:\masm32\include\msvcrt.inc
include C:\masm32\include\windows.inc
 
includelib C:\masm32\lib\kernel32.lib; импорт библиотеки.
includelib C:\masm32\lib\msvcrt.lib
 
include C:\masm32\macros\macros.asm; для функции printf.
 
.data
cnt dd 0 ; количество символов выведенных в консоль.
hin dd 0 ; ввод.
fName db "simple.txt",0; имя файла.
buf   dd 255 dup (0)
.code
MAIN:
 
call input_consol; ввод в консоль, подсчет символов в строке.
call write_in_file; записать в файл.
call read_file; читать файл.
 
  invoke  crt__getch; ждать нажатия.
  invoke ExitProcess, 0; вызов функции выхода, передаем 1 параметр 4 байта.
 
read_file: ;
  lea ebx, [fName]; имя файла.
 
  invoke CreateFile, ebx, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0
  mov hin, eax; получить хендл файла.
  invoke GetFileSize, hin, 0;  размер файла.
  mov cnt, eax; сохранить размер файла.
  push cnt; отправить количество символов в стек.
  lea eax, [buf]; буфер.
  lea ebx, cnt; размер файла.
  invoke ReadFile, hin, ebx, cnt, eax, 0; указатель на строку находится в ebx.
 
  printf ("str = %s\n", ebx)
  invoke CloseHandle, hin
 
   invoke GetStdHandle, -11; код вывода.
   mov hin,eax; получить хендл файла.
   pop cnt
 
   printf ("len str = %d\n", cnt)
   invoke WriteConsoleA, hin, ADDR buf, cnt, 0, 0
   invoke CloseHandle, hin
  ret
 
write_in_file: ;
  push ebx
  lea ebx, [fName]; имя файла.
    invoke CreateFile, ebx, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, 0
    mov hin, eax; хендл файла.
    pop ebx; строку, которую ввели в консоль
    invoke WriteFile, hin, ebx, cnt, 0, 0;
    invoke CloseHandle, hin;
  ret
 
  input_consol: ; ввод в консоль, подсчет символов в строке.
  invoke GetStdHandle, -10; код ввода. получить хендл.
  mov hin,eax; отправить в eax.
  lea eax, cnt; отправить кол-во символов в eax.
  lea ebx, buf ; отправить адрес строки в ebx.
  invoke ReadConsoleA, hin, ebx, 255, eax, 0
  push ebx
  invoke CloseHandle, hin; закрыть ввод.
  invoke lstrlen, ebx
  sub eax, 2
  mov cnt, eax ; количество символов в строке
  pop ebx
  ret
 
 _TEXT ENDS
 
END MAIN
0
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8644 / 4479 / 1669
Регистрация: 01.02.2015
Сообщений: 13,883
Записей в блоге: 11
12.06.2020, 00:49
Лучший ответ Сообщение было отмечено Егор Щербанов как решение

Решение

Для вывода целых чисел - требуется преобразовать их в строку и строку выводить.
Скорее всего у вас ошибка в том, что перепутаны параметры. Я в своих тестовых программках использую переменные с именами, как в описаниях MSDN, поэтому труднее перепутать порядок.
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
.686
.model flat, stdcall
option casemap :none
 
        include \masm32\include\windows.inc
 
        include \masm32\include\user32.inc
        include \masm32\include\kernel32.inc
        include \masm32\include\masm32.inc
 
        includelib \masm32\lib\user32.lib
        includelib \masm32\lib\kernel32.lib
        includelib \masm32\lib\masm32.lib
.const
        szPrompt        db      0Dh, 0Ah, 'Enter a string:', 0Dh, 0Ah, 0
        aszFileSize     db      0Dh, 0Ah, 'size of file: %d', 0
        szPressEnter    db      0Dh, 0Ah, 0Dh, 0Ah, 'Press ENTER to exit', 0
        aszFileName     db      'outfile.txt', 0
 
.data?
        hConsoleOutput  HANDLE  ?
        hConsoleInput   HANDLE  ?
        hFile           HANDLE  ?
        aBuffer         db      1024 dup(?)
        nBufLen         dd      ?
        nCount          dd      ?
        temp            dd      ?
 
.code
 
input   proc
        ;вывод приглашения к вводу строки
        invoke  WriteConsole, hConsoleOutput, ADDR szPrompt,\
                LENGTHOF szPrompt-1, ADDR nBufLen, NULL
        ;ввод строки
        invoke  ReadConsole, hConsoleInput, ADDR aBuffer,\
                LENGTHOF aBuffer-1, ADDR nBufLen, NULL
        lea     esi,    [aBuffer]       ;удаление из буфера
        mov     eax,    [nBufLen]       ;символов перевода строки
        sub     eax,    2
        ;сохранение длины введённой строки
        mov     [nBufLen],      eax
        ;в конец строки помещаем 0 - ограничитель строки
        mov     [esi+eax],      byte ptr 0
        ret
input   endp
 
write_to_file   proc
        invoke  CreateFile,     ADDR aszFileName,\      ;lpFileName
                                GENERIC_WRITE,\         ;dwDesiredAccess
                                NULL,\                  ;dwShareMode
                                NULL,\
                                CREATE_ALWAYS,\
                                FILE_ATTRIBUTE_NORMAL,\
                                NULL
        cmp     eax,    INVALID_HANDLE_VALUE
        jne     @f
                ;сообщение об ошибке открытия на запись
                invoke  GetErrDescription,      0
                jmp     @@EndOfProc
        @@:
        mov     [hFile],        eax
 
        invoke  WriteFile,      [hFile], ADDR aBuffer, [nBufLen],
                ADDR temp, NULL
        test    eax,    eax
        jne     @f
                ;сообщение об ошибке при записи
                invoke  GetErrDescription,      0
                jmp     @f
        @@:
 
        invoke  CloseHandle,    [hFile]
@@EndOfProc:
        ret
write_to_file   endp
 
read_from_file  proc
        ;из файла считано 0 байт
        mov     [nCount],       0
        ;открытие файла
        invoke  CreateFile,\
                        ADDR aszFileName,\      ;file name
                        GENERIC_READ,\          ;open for reading
                        0,\                     ;do not share
                        NULL,\                  ;default security (no security)
                        OPEN_EXISTING,\         ;existing file only
                        FILE_ATTRIBUTE_NORMAL,\ ;normal file
                        NULL                    ;no attr. template
        mov     [hFile],        eax
        cmp     eax,    INVALID_HANDLE_VALUE
        jne     @f
                ;сообщение об ошибке открытия на чтение
                invoke  GetErrDescription,      0
                jmp     @@EndOfProc
        ;чтение файла и вывод на экран
        @@:
        @@ReadFromFile:
                invoke  ReadFile,       [hFile], ADDR aBuffer, SIZEOF aBuffer,\
                        ADDR nBufLen, NULL
                or      eax,    eax
                jne     @f
                        ;сообщение об ошибке чтения
                        invoke  GetErrDescription,      0
                        jmp     @@BreakRead
                ;проверяем состояние "конец файла", .к. чтение не вызовет ошибку
                @@:
                mov     eax,    [nBufLen]
                add     [nCount],       eax
                cmp     [nBufLen],      0
                jz      @@BreakRead
                ;раз очередная порция считана - выводим её
                invoke  WriteConsole,   [hConsoleOutput], ADDR aBuffer,\
                        [nBufLen], ADDR temp, NULL
        jmp     @@ReadFromFile
@@BreakRead:
        invoke  CloseHandle,    [hFile]
@@EndOfProc:
        ;вывод сообщения о количестве считанных байт из файла
        invoke  wsprintf,       ADDR aBuffer, ADDR aszFileSize, [nCount]
        mov     [nBufLen],      eax
        invoke  WriteConsole,   [hConsoleOutput], ADDR aBuffer,\
                [nBufLen], ADDR nBufLen, NULL
        ret
read_from_file  endp
 
main    proc
        ; получение описателей ввода и вывода консоли
        invoke  GetStdHandle,   STD_INPUT_HANDLE
        mov     [hConsoleInput],        eax
        invoke  GetStdHandle,   STD_OUTPUT_HANDLE
        mov     [hConsoleOutput],       eax
        ;вввод исходных данных
        call    input
        ;для кириллицы выполним перекодировку OEM to ANSI
        ;invoke  OemToChar,      ADDR aBuffer, ADDR aBuffer
        ;обработка:
        call    write_to_file
        call    read_from_file
        ;ожидание нажатия ENTER
        invoke  WriteConsole, hConsoleOutput, ADDR szPressEnter,\
                LENGTHOF szPressEnter - 1, ADDR nBufLen, NULL
        invoke  ReadConsole, hConsoleInput, ADDR aBuffer,\
                LENGTHOF aBuffer-1, ADDR nBufLen, NULL
 
        invoke  ExitProcess, 0
main    endp
 
end     main
1
11 / 10 / 2
Регистрация: 19.02.2018
Сообщений: 393
12.06.2020, 04:31  [ТС]
Лучший ответ Сообщение было отмечено ФедосеевПавел как решение

Решение

ФедосеевПавел, спасибо огромное за вашу помощь, вы мне очень помогли.

решил так.
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
.data
cnt dd 0 ; количество символов выведенных в консоль.
hin dd 0 ; ввод.
fName db "simple.txt",0; имя файла.
buf   dd 255 dup (0)
 
.code
MAIN:
 
call input_consol; ввод в консоль, подсчет символов в строке.
call write_in_file; записать в файл.
call read_file; читать файл.
 
  invoke  crt__getch; ждать нажатия.
  invoke ExitProcess, 0; вызов функции выхода, передаем 1 параметр 4 байта.
 
read_file: ;читать файл.
  lea ebx, [fName]; имя файла.
 
  invoke CreateFile, ebx, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0
  mov hin, eax; получить хендл файла.
  invoke GetFileSize, hin, 0;  размер файла.
  mov cnt, eax; сохранить размер файла.
  push cnt; отправить количество символов в стек.
  invoke ReadFile, hin, ADDR buf, cnt, 0, 0; указатель на строку находится в ebx.
  invoke CloseHandle, hin
 
   invoke GetStdHandle, -11; код вывода.
   mov hin,eax; получить хендл файла.
   pop cnt
   printf ("len str = %d\n", cnt)
   invoke WriteConsoleA, hin, ADDR buf, cnt, 0, 0
   invoke CloseHandle, hin
  ret
 
write_in_file: ; записать в файл текст из консоли
  lea ebx, [fName]; имя файла.
    invoke CreateFile, ebx, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, 0
    mov hin, eax; хендл файла.
    invoke WriteFile, hin, ADDR buf, cnt, 0, 0;
    invoke CloseHandle, hin;
  ret
 
  input_consol: ; ввод в консоль, подсчет символов в строке.
  invoke GetStdHandle, -10; код ввода. получить хендл.
  mov hin,eax; отправить в eax.
  lea eax, cnt; отправить кол-во символов в eax.
  lea ebx, buf ; отправить адрес строки в ebx.
  invoke ReadConsoleA, hin, ebx, 255, eax, 0
  push ebx
  invoke CloseHandle, hin; закрыть ввод.
  invoke lstrlen, ebx
  sub eax, 2
  mov cnt, eax ; количество символов в строке
  pop ebx
  ret
 
 _TEXT ENDS
 
END MAIN
0
 Аватар для Ethereal
6773 / 2741 / 385
Регистрация: 17.02.2013
Сообщений: 4,048
14.06.2020, 09:01
Цитата Сообщение от ФедосеевПавел Посмотреть сообщение
А значение ebx никто не обещал сохранять после вызова WinAPI.
Обещал.

stdcall

The stdcall[4] calling convention is a variation on the Pascal calling convention in which the callee is responsible for cleaning up the stack, but the parameters are pushed onto the stack in right-to-left order, as in the _cdecl calling convention. Registers EAX, ECX, and EDX are designated for use within the function. Return values are stored in the EAX register.

stdcall is the standard calling convention for the Microsoft Win32 API and for Open Watcom C++.

Добавлено через 9 минут
Вот тут в MSDN
https://docs.microsoft.com/ru-... ew=vs-2019
сказано:

Компилятор создает код пролога и эпилога для сохранения и восстановления регистров ESI, EDI, EBX и EBP, если они используются в функции.

и если на этой странице клацнуть на частный случай __stdcall то там будет

Соглашение о вызовах __stdcall используется для вызова функций API Win32.

Добавлено через 13 минут
А, там уже Argogo об этом уже написал.

Добавлено через 6 минут
Цитата Сообщение от ФедосеевПавел Посмотреть сообщение
Чтобы не заморачиваться с запоминанием этих особенностей - всё, что нужно для дальнейшей работы программы сохраняю в переменных, в стеке, но не собираюсь доверять чьим-то реализациям процедур.
Да ты можешь писать как угодно, а вот мозги ТС-ам компостировать нельзя. Если забыл - погугли.
Пишу для Windows, использую Windows API, но реализациям функций Windows API не собираюсь доверять. Раздвоение личности какое-то.
0
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8644 / 4479 / 1669
Регистрация: 01.02.2015
Сообщений: 13,883
Записей в блоге: 11
14.06.2020, 10:39
Да, так и есть. На память не помню, в справку смотреть лень.

Собственно, ошибка в программе была в путанице подстановки регистров в качестве аргументов при вызове функций WinAPI x32. Использование регистров вместо символьных имён переменных в исходниках было не оправдано, приводило к путанице. Если бы топикстартер внял этому - программа была бы исправлена на 5-6 часов раньше. И после этого, имея корректный исходник, можно его улучшать, заменяя переменные на регистры из списка сохраняемых при вызовах.
Это я и хотел сказать, более - несколько раз повторил, привёл рабочие примеры.

Можно придираться, что не помню соглашения о вызовах, но задача была в другом - убедить ТС проверять порядок подстановки параметров в вызов функции, и делать это на данном этапе учёбы было лучше через именованные переменные, а не регистры.

IMHO, так правильное замечание замедлило работу на 5-6 часов.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
14.06.2020, 10:39
Помогаю со студенческими работами здесь

Считать N строк из текстового файла, причем неизвестна длина каждой строки
Требуется считать N (N<100000) строк из текстового файла, причем неизвестна длина каждой строки. Код программы: uses crt; var...

Напечатать все строки текстового файла, длина которых меньше заданного числа
2.Дан текстовый файл. Напечатать все строки, длина которых меньше заданного числа. Помогите, пожалуйста

Напечатать все строки текстового файла, длина которых меньше заданного числа
Дан текстовый файл. Напечатать все строки, длина которых меньше заданного числа.

Напечатать все строки текстового файла, длина которых меньше заданного числа
Дан текстовый файл. Напечатать все строки, длина которых меньше заданного числа.

Напечатать все строки текстового файла, длина которых равна данному числу
Дан текстовый файл. Напечатать все строки, длина которых равна данному числу.Windows Forms using System; using System.Text; using...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru