Форум программистов, компьютерный форум, киберфорум
Assembler, MASM, TASM
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/6: Рейтинг темы: голосов - 6, средняя оценка - 4.67
0 / 0 / 0
Регистрация: 25.10.2010
Сообщений: 18

перенести создание файла в основную нерезидентную часть

10.12.2010, 10:42. Показов 1176. Ответов 8
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Ребята, пожалуйста, окажите помощь.
Написал программу резидeнтную, которая запиcывaет в фaйл то, что на экрaнe.
В ДОСБОКСе работает отлично, но под 98 виндой не идет, виснет при создании файла.
Сказали, что происходит из-за того, что файл создается и пишется в резидентной части.

Как перенести создание файла в основную нерезидентную часть (init)? То есть дескриптор оставить резиденту, чтоб он туда видеостраницу писал.

Пробовал, но получается так: файл создается, но в него ничего не пишется и он не закрывается.

Вот код рабочей программы:
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
.286
cseg segment
assume cs:cseg, ds:cseg, ss:cseg, es:cseg      
org 100h        ;Префикс программного сегмента(служ. инф., параметры ком.строки)
 
begin:
       jmp init     ;на метку инициализации (начало программы)
 
; === процедура обработки 09h прерывания (клавиатура) ===
int_09h_proc proc
 
       cmp ax, 0FFAAh   ;Проверка на то, что загружаем в первый раз
       jne continue ;Если не проверка, то продолжаем далее
       xchg ah,al   ;Меняем местами FF и AA - это флаг признак,что резидент загружен
       iret             ;выход из прерыв.-возврат в программу, восстанавливая из стека значения регистров IP, CS и FLAGS.
 
continue:
       push ax
       push es
 
       xor ax,ax 
       mov es,ax
       mov al,es:0417h  ; берем байт статуса клавиатуры - нажата ли клавиша (BIOS data area)
       test al,00000100b  ; проверяем не нажат ли Ctrl
       jz not_ctrl_s ; выходим, если нет
 
               in al,60h ; принимаем скан-код с клавиатуры
               cmp al, 2dh  ;  сравниваем со скан кодом X
               je unload    ;Выгружаем, если совпало
               cmp al,1fh ; сравниваем со скан кодом S
               jne not_ctrl_s ; выходим если это не он. Иначе продолжаем
 
       pusha     ;(push All registers) помещает в стек регистры ax, cx, dx, bx, sp, bp, si, di.
       pushf     ;помещает в стек регистр флагов (нуля, переноса...)
 
       cli      ;запрещаем прерывания, чтобы не было конфликтов
       push es      ;и сегментные регистры
       push ds
 
       push 0b800h      ;ds должен быть равен сегменту видеобуфера 0-ой страницы
       pop ds           ;0b800h - сегмент этой страницы теперь в ds
 
       push 0b900h  ;es - 1-ой страницы
       pop es       ;0b900h - сегмент этой страницы теперь в es
 
 
       xor di,di    ;аннулируем di и si
       xor si,si
 
       mov cx,25    ;на экране 25 строк...
next_line:
       push cx
       mov cx,80    ;...80 символов в каждой строке
next_symbol:
       lodsw        ;берем первый символ и атрибут в ax по адресу ds:si (lodsw)
       stosb        ;заносим символ без атрибута из al в 1-ую
            ;видеостраницу (stosb) - из [es:di]
       loop next_symbol ;следующий символ... (пока cx не станет 0)
 
       mov ax,0a0dh ;добавляем в конце каждой строки возврат каретки
       stosw        ;перевод строки
       pop cx
       loop next_line   ;следующая строка... (пока cx не станет 0)
 
       push cs      ;ds должен быть равен сегменту, в котором мы сейчас
       pop ds       ;находимся (а cs всегда на этот сегмент и указывает)
files:
       mov ax,3d02h ;функция открытия файла 3d - открыть, 02h - для чтения/записи
       mov dx,offset screen_file_name   ;ds:dx указывают на путь и имя файла
       int 21h      ;создаем файл в текущем каталоге
       jnc file_opened  ;Если файл открыт (он существует), то пропускаем этап создания
       mov ax,3c02h     ;Функция создания файла 3сh, 02h - для чтения и записи
       xor cx,cx        
       int 21h
 
file_opened:
       xor cx,cx
       xor dx,dx
 
       mov bx,ax        ;Тут устанавливаем указ. в файле 42h-устанавливаем указатель в файл,
       mov ax,4202h ;02h - с послед. места
       int 21h
 
       push 0b900h  ;ds должен указывать на 1-ую видеостраницу
       pop ds
 
       mov ah,40h   ;функция записи в файл
       xor dx,dx    ;ds:dx должны указывать на буфер, где находятся данные
       mov cx,2050  ;кол-во записываемых байт (80*25 + 2*25 = 2050)
       int 21h      ;записываем в созданный файл содержимое экрана...
 
       mov ah,3eh   ;функция закрытия файла
       int 21h
 
       pop ds       ;восстановим сохраненные регистры
       pop es
 
       sti      ;разрешим прерывания
 
       popf             ;Восстанавливаем флаги
       popa     ;И регистры
 
not_ctrl_s:
 
       pop es            ; восстанавливаем регистры
       pop ax
 
       jmp dword ptr cs:[int_09h_vect]  ;передаем управление оригинальному обработчику 09h...
    
 
unload:                            ;Выгружаем наш обработчик прерывания 09h из оперативной памяти
 
       mov ax,2509h                 ;Для этого функцией 25h  
                                    ;загружаем указатель на оригинальный обработчик               
       lds dx,[cs:int_09h_vect]     ;lds (load ds) - загружает в ds = cs:int_09h_vect
                                       в dx = cs:int_09h_vect+2
       int 21h
 
       mov es, [cs:2ch]
       mov ah,49h
       int 21h ; освободить память
       push cs
       pop es
       mov ah, 49h
       int 21h
 
       pop es             ; восстанавливаем регистры
       pop ax
 
       jmp dword ptr cs:[int_09h_vect]
 
int_09h_vect dd ?       ;переменная для хранения адреса 09h прерывания (оригинального)
screen_file_name db 'c:\screen.txt',0   ;имя файла, куда занесем содержимое экрана
 
int_09h_proc endp
 
; ===============================================================
; инициализация (подготовка и настройка резидента)
init:
 
       mov ax, 0FFAAh ;Три строки - проверка, не загружен ли уже резидент
       int 9h          ;Для этого помещаем в ax нигде не встречающееся число
       cmp ax, 0AAFFh  ;И если загружаем, то меняем дробную/целую часть
      
       je already_running    ;Если 
       push es
       mov ax,3509h
       int 21h      ;получим и сохраним адрес (вектор) 09h прерывания
       mov word ptr int_09h_vect,bx ;вначале младшее слово (смещение)...
       mov word ptr int_09h_vect+2,es   ;затем старшее (сегмент)
 
       mov ax,2509h   ;25h устанавливает для al (у нас 09h) значение элемента таблицы векторов=ds:dx
       mov dx,offset int_09h_proc       ;А вот и dx - сюда адрес нового обработчика прерывания 09h
       int 21h      ;Все. "повесим" нашу процедуру на 09h прерывание (при помощи функции 25h)
 
       mov ah,9                    ;Тут просто сообщение, говорящее о том, что программа запустилась
       mov dx,offset mess_hello    ;И загрузилась
       int 21h
 
       mov dx,offset init     ;В dx - адрес метки инициализации
       pop es
       int 27h      ;оставим программу резидентной в памяти, выходим в DOS
 
already_running:
       mov ah, 9
       mov dx, offset in_memory  ;Выводим сообщение о том, что уже запущено
       int 21h
       mov ax, 4c00h      ;Выход (из родительского процесса - init)
       int 21h
 
in_memory db 'Already running...',0ah,0dh,'$'     ;наше сообщение
;А ниже - сообщение, которое грузится при первоначальном запуске программы
mess_hello db 'Press Ctrl+s to write the screen to file C:\SCREEN.TXT',0ah,0dh,'$'
 
cseg ends
end begin
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
10.12.2010, 10:42
Ответы с готовыми решениями:

Каким образом из файла-ресурса меню должно передаться в основную часть программы?
Ночи доброй, форумчане! Вопрос следующий: что именно описывается в .h-файле, каким образом из файла-ресурса меню должно передаться в...

Cтруктура программы. Где пишем основную часть кода?
Добрый всем денек, есть ламерский вопрос, не пинайте ногами. Создаю проект C# в VS 2005, стандартный код, создаваемый по умолчанию вы...

Основную часть кода вынести из класса формы в отдельный класс
У меня весь код находится в коде формы, а мне нужно основную часть написать в отдельно созданном классе, мб кто-нибудь покажет как все...

8
1779 / 757 / 153
Регистрация: 03.06.2009
Сообщений: 5,940
10.12.2010, 13:42
;Особенности резидентных программ
;TSR-программы имеют некоторые особенности, отличающие их от "нормальных" программ.
;Им не разрешается использовать DOS-прерывания, когда вздумается. Это связано с тем, что DOS проектировалась как однозадачная операционная система, поэтому модули DOS не обладают свойством реентерабельности (повторной входимости). Что это означает на практике?
;Допустим, Ваша программа записывает длинный файл на диск. Во время записи вы (возможно, случайно) нажали клавишу, активизирующую TSR-программу записи содержимого экрана в файл.
;Теперь доступа к диску требуют две программы - прикладная, записывающая длинный файл, и Ваша TSR-программа. Запись файла из прикладной программы приостановится, далее произойдет запись копии экрана в файл, после чего возобновится запись файла из прикладной программы. Все было бы хорошо, если бы прикладная программа и TSR-программа не использовали одни и те же внутренние области данных DOS для работы с диском. При запуске TSR-программа безвозвратно испортит текущее состояние служебных областей данных, которые прикладная программа использовала при записи на диск.
;И таких примеров можно привести много. BIOS также далеко не весь реентерабельный. TSR-программа может смело использовать разве лишь прерывание 16h для работы с клавиатурой, которое реентерабельно. Для вывода на экран лучше всего использовать непосредственную запись символов в видеопамять дисплейного адаптера.
;Не стоит пользоваться многими функциями библиотеки Quick C, так как они могут вызывать прерывания DOS. Например, функция malloc() вызывает прерывание DOS для определения размера свободной памяти в системе.
;Могут возникнуть трудности с использованием арифметических действий с числами в формате плавающей запятой, так как функция _dos_keep() при завершении программы восстанавливает прерывания, использовавшиеся для эмуляции арифметики с плавающей запятой и для работы с арифметическим сопроцессором.
;Некоторые из перечисленных проблем (те, что связаны с использованием прерываний DOS) можно решить с помощью недокументированного прерывания INT 28h.
;Это прерывание вызывается DOS при ожидании ввода с клавиатуры. В этот момент вы можете использовать любое прерывание DOS, кроме функций от 00h до 0Сh прерывания INT 21h. Утилита спулинга печати PRINT.COM использует это прерывание.
;Можно рекомендовать следующий способ использования прерывания 28h. Обработчик прерывания 9 отслеживает нажатие клавиши, которая должна активизировать TSR-программу. Обнаружив эту клавишу (или комбинацию клавиш), обработчик прерывания 9 устанавливает флаг запроса на активизацию TSR-программы и завершает свою работу обычным способом.
;Ваша TSR-программа должна создать свой обработчик прерывания 28h и сцепить его со стандартным. Каждый раз, когда DOS ожидает ввода с клавиатуры (в этот момент DOS не использует сама свои прерывания), вызывается прерывание 28h. Ваш обработчик проверяет флаг активизации, устанавливаемый обработчиком прерывания 9, и если флаг установлен, TSR-программа активизируется и может пользоваться услугами DOS, в частности, файловой системой.
;Разумеется, после выполнения всех необходимых действий TSR-программа должна сбросить флаг активизации.
0
0 / 0 / 0
Регистрация: 25.10.2010
Сообщений: 18
11.12.2010, 11:55  [ТС]
Это что же получается: вообще никак не осуществить создание файла в резидентной части?
0
1779 / 757 / 153
Регистрация: 03.06.2009
Сообщений: 5,940
11.12.2010, 11:59
Можно, но только в определенное время, когда именно, читайте в посте №2
0
0 / 0 / 0
Регистрация: 25.10.2010
Сообщений: 18
11.12.2010, 12:06  [ТС]
Точнее, придется переделывать программу, используя 28h прерывание?

Подскажите, очень прошу, как грамотно это сделать?
Новый обработчик прерывания 09h вообще убирать? Устанавливать вектор для 28h?
0
1779 / 757 / 153
Регистрация: 03.06.2009
Сообщений: 5,940
11.12.2010, 12:08
я делал так:
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
New09Obrab  proc        ; новый обработчик прерывания int09h
 
    pushf           ; заносим флаги в стек, поскольку iret в конце оригинального обработчика заберет один экземпляр флагов из стека
    call    dword   ptr CS:[Old09]  ; вызов оригинального обработчика
    cli         ; запретить прерывания
    pushf           ; сохранить флаги
    pusha           ; сохранить регистры общего назначения
    mov cs:work,0   ; сбрасываем признак активации
    in  al,60h      ; читаем из порта клавиатуры скан-код нажатойй клавиши
    cmp     al,3bh      ; это f1?
    jz  fx_pressed
    cmp     al,3ch      ; это f2?
    jz  fx_pressed
    cmp     al,3dh      ; это f3?
    jz  fx_pressed
    cmp     al,3eh      ; это f4?
    jz  fx_pressed
    jmp skipwork    ; иначе просто пропускаем
fx_pressed:
    mov cs:work,1   ; устанавливаем признак активации
    sub al,3bh      ; по нажатой клавище получаем номер страницы: f1-0,f2-1,f3-2,f4-3
    mov ah,0
    shl ax,12       ; расчитываем смещение страницы
    push    es      ; сохраняем сегментные регистры, поскольку они не сохраняются командой pusha
    push    ds              ;
    push    cs      ; установка es:di в начало буфера программы и ds:si в начало страницы
    pop es
    push    0b800h
    pop ds
    mov si,ax       ; адрес начала страницы
    mov di, offset scrbuff; адрес начала буфера в памяти
    cld                     ; устанавливаем прямой режим увеличения адресов при работе со строковыми командами
    mov cx,0        ; обход страницы
    mov bl,80       ; делитель
scr:
    lodsw           ; команда загрузки из последовательности(цепочки) в аккумулятор AX
    stosb           ; сохраняем в цепочке только код символа
    inc cx      ; увеличиваем счетчик
    mov ax,cx
    div bl      
    test    ah,ah       ;достигнут ли конец строки экрана?
    jnz ncrlf
    mov ax,0a0dh    ;если да, то добавляем в буфер символы конца строки
    stosw
ncrlf:  cmp cx,2048     ;обходим пока не закончится видеостраница
    jnz scr
 
    pop ds      ; восстанавливаем сегментные регистры
    pop es
skipwork:
    popa            ; восстанавливаем регистры общего назначения
    popf            ; восстанавливаем флаги
    sti         ; разрешить прерывания
    iret            ; выход из прерывания
endp
 
New28Obrab  proc        ; новый обработчик прерывания int28h
 
    pushf           ; заносим флаги в стек, поскольку iret в конце оригинального обработчика заберет один экземпляр флагов из стека
    call    dword   ptr CS:[Old28]  ; вызов оригинального обработчика
    pushf           ; сохранить флаги
    pusha           ; сохранить регистры общего назначения
    cmp cs:work,1   ; проверяем фдаг активации
    jnz skip28      ; выход из обработчика, если флаг сброшен
    push    es      ; сохраняем сегментные регистры, поскольку они не сохраняются командой pusha
    push    ds              ;
    push    cs      ; установка es и ds равным cs
    pop es
    push    es
    pop ds
    mov ah,41h      ;удаляем файл page.txt(если он есть), чтобы не мешать созданию нового
    mov dx,offset fname
    int 21h
    mov ah,3ch      ;создаем файл page.txt
    mov cx,0
    mov dx,offset fname
    int 21h
    jc  stop28      ;если ошибка, то пропускаем дальнейшие файловые операции
    mov handle,ax   ;сохраняем хэндл
    mov bx,ax
    mov ah,40h      ;записываем на диск сожержимое буфера
    mov cx,800h + 26*2
    mov dx,offset scrbuff
    int 21h
    jc  stop28
    mov bx,handle   ;и закрываем файл
    mov ah,3eh
    int 21h
 
 
 
stop28: mov cs:work,0   ;сбрасываем флаг активации
    pop ds      ; восстанавливаем сегментные регистры
    pop es
skip28:
    popa            ; восстанавливаем регистры общего назначения
    popf            ; восстанавливаем флаги
    iret            ; выход из прерывания
endp
работало и из винды
0
0 / 0 / 0
Регистрация: 25.10.2010
Сообщений: 18
11.12.2010, 12:14  [ТС]
Спасибо большое! Сейчас разбираться буду.
А что программа делает, можно уточнить?
0
1779 / 757 / 153
Регистрация: 03.06.2009
Сообщений: 5,940
11.12.2010, 12:15
сохраняет содержимое экрана в файл
0
0 / 0 / 0
Регистрация: 25.10.2010
Сообщений: 18
11.12.2010, 12:35  [ТС]
Я извиняюсь, а это полный текст программы?

Добавлено через 8 минут
А, это же процедуры-обработчики.
А можно попросить основную часть? Или расскажите, меняете ли вектора прерывания и что у Вас является флагом загрузки резидента?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
11.12.2010, 12:35
Помогаю со студенческими работами здесь

Создание файла, часть имени которого - нумерованная строка
Добрый день. Сейчас постараюсь объяснить... Есть БАТ @echo off chcp 1251 play c:\ cd c:\zirkon\new copy c:\zirkon\new\iz...

Вынести основную часть кода кода в отдельную функцию
помогите пожалуйста переделать это на функцию... #include <locale.h> #include <conio.h> int main() { setlocale(0,""); ...

Перемещение текста файла в основную программу
доброго времени суток, подскажите пожалуйста, как в паскале обратится к файлу X в папке Y чтобы текст этого файла перешел в основную...

Передача данных из *.cs файла в основную форму
Здравствуйте. Вопрос следующий. Есть *.cs файл с методами прикрепленный к проекту. После выполнения метода мне нужно результат передать в...

Перенести часть строки в int
подскажите пожалуйста есть вот такая строка string str ="3-12:39.00"; хочу взять первый элемент из строки то есть 3 пытаюсь сделать это...


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

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru