Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Asm для начинающих > Реализовать вызов процедуры через системное прерыв


Автор: mycodeurnightmare 20.9.2015, 01:54
Доброго времени суток. Вот задание: Реализовать вызов процедуры через системное прерывание для создания нового массива из положительных чисел произвольного массива однобайтных чисел. Входные параметры: адрес исходного массива, его длина, адрес нового массива.
Вот код с процедурой. Но не понимаю теперь как правильно записать адрес собственной процедуры в вектор прерывания. :С Заранее огромное спасибо.
Код

.386
dseg segment use16
mass1 db 1,-20,30,40,-30,50,-40,100,-45,2 
dseg ends
eseg segment use16
mass2 db 10 dup(?)
eseg ends
cseg segment use16
assume ds:dseg, cs:cseg, es:eseg
;загрузка регистров-указателей сегментов ds, es
code:  mov cx, dseg 
       mov ds, cx
       mov cx, eseg
       mov es, cx
;входные параметры процедуры
lea si, ds:mass1
mov cx,10
lea di, es:mass2
call maspr
;завершение исполнения
mov ah, 4ch 
int 21h
;объявление поцедуры
maspr proc
cycl: cmp byte ptr ds:[si], 0
jl m1
movsb
jmp m2
m1:inc si
m2:loop cycl
ret 
maspr endp
cseg ends
end code

Автор: ФедосеевПавел 20.9.2015, 11:32
К сожалению, у меня уже нет WinXP, где легко работалось с DOS, и нет виртуальной машины с DOS. Поэтому, подскажу "на словах" в общем виде.
1. Почитайте о прерываниях, о перехвате прерываний, восстановлении исходных векторов.
2. Сделайте перехват 21h прерывания по какой-нибудь неиспользуемой функции (http://www.delorie.com/djgpp/doc/rbinter/ix/21/, или http://www.ctyme.com/intr/int.htm) - например 74h. В своём обработчике сделайте проверку - если функция 74h, то вызывайте maspr, иначе отдавайте управление старому обработчику.
3. В программе вызывайте вместо maspr прерывание int 21h fn=74h.
4. Перед завершением программы восстанови исходный обработчик.

Чтение вектора прерывания - int 21h fn=35h. Запись вектора прерывания int 21h fn=25h.

Внизу представлены примеры.
http://forum.vingrad.ru/topic-331174.html - не проверял, но как пример подойдёт.
http://forum.vingrad.ru/topic-341801.html#
http://forum.vingrad.ru/topic-100542.html

Автор: mycodeurnightmare 20.9.2015, 14:12
Цитата(ФедосеевПавел @ 20.9.2015,  11:32)
К сожалению, у меня уже нет WinXP, где легко работалось с DOS, и нет виртуальной машины с DOS. Поэтому, подскажу "на словах" в общем виде.
1. Почитайте о прерываниях, о перехвате прерываний, восстановлении исходных векторов.
2. Сделайте перехват 21h прерывания по какой-нибудь неиспользуемой функции (http://www.delorie.com/djgpp/doc/rbinter/ix/21/, или http://www.ctyme.com/intr/int.htm) - например 74h. В своём обработчике сделайте проверку - если функция 74h, то вызывайте maspr, иначе отдавайте управление старому обработчику.
3. В программе вызывайте вместо maspr прерывание int 21h fn=74h.
4. Перед завершением программы восстанови исходный обработчик.

Чтение вектора прерывания - int 21h fn=35h. Запись вектора прерывания int 21h fn=25h.

Внизу представлены примеры.
http://forum.vingrad.ru/topic-331174.html - не проверял, но как пример подойдёт.
http://forum.vingrad.ru/topic-341801.html#
http://forum.vingrad.ru/topic-100542.html

Спасибо за помощь, но... наверное я что-то совсем не так делаю или не понимаю, как оно работает, ибо резидент не вызывается.  
Код

.386
dseg segment use16
mass1 db 1,-20,30,40,-30,50,-40,100,-45,2
vect dd ?
dseg ends
eseg segment use16
mass2 db 10 dup(?)
eseg ends
cseg segment use16
assume ds:dseg, cs:cseg, es:eseg
;загрузка регистров-указателей сегмента ds
code:  mov cx, dseg 
       mov ds, cx
       mov cx, eseg
       mov es, cx
;сохраним адрес обработчика прерываний
mov ah,35h
mov al,69h
int 21h                
mov word ptr ds:vect,bx     ;Вначале младшее слово (смещение)
mov word ptr ds:vect+2,es ;Затем старшее (сегмент)
push ds

mov cx, cs
mov ds, cx
lea dx,maspr
mov ah,25h
mov al,69h
int 21h
pop ds    

;входные параметры процедуры    
mov cx,10
lea si, ds:mass1
lea di, es:mass2
;вызовем резидентный обработчик прерывания
mov ah, 69h
mov al,0
int 21h
;восстановим старый обработчик прерывания
mov dx,word ptr ds:vect
mov ds, word ptr ds:vect+2
mov ah, 25h
mov al,69h
int 21h
;завершение исполнения
mov ah, 4ch    
int 21h
;объявление поцедуры
maspr proc
cycl: cmp byte ptr ds:[si], 0
jl m1
movsb
jmp m2
m1:inc si
m2:loop cycl
iret    
maspr endp
cseg ends
end code

Автор: ФедосеевПавел 20.9.2015, 16:43
А это не будет резидентом, просто на время запуска своей программы к некоторым возможностям можно будет обратиться через программное прерывание.

По-моему здесь нужно ASSUME
Код

mov cx, cs
mov ds, cx
assume ds:cseg  <----- или assume ds:nothing
lea dx,maspr   <----- а здесь, может быть mov dx, OFFSET maspr или lea dx, cs:maspr
mov ah,25h
mov al,69h
int 21h
pop ds
assume ds:dseg  <-----

Кроме того, это код установки прерывания int 69h. Пусть будет 69, но тогда в дальнейшем его и нужно вызывать, а не 21h для вызова maspr.

Ещё нужно объявление стека размером хотя бы 1кБайт.

Почитай учебники. Мне сложно давать советы без виртуальной машины с DOS.

Автор: mycodeurnightmare 20.9.2015, 16:57
Спааасибо Вам огромное, всё заработало.  smile 
Код

.386
dseg segment use16
mass1 db 1,-20,30,40,-30,50,-40,100,-45,2
vect dd ?
dseg ends
eseg segment use16
mass2 db 10 dup(?)
eseg ends
cseg segment use16
assume ds:dseg, cs:cseg, es:eseg

;загрузка регистров-указателей сегмента ds
code:  mov cx, dseg 
       mov ds, cx
       mov cx, eseg
       mov es, cx

;сохраним адрес обработчика прерываний
push es
mov ah,35h
mov al,69h
int 21h                
mov word ptr ds:vect,bx     ;Вначале младшее слово (смещение)
mov word ptr ds:vect+2,es ;Затем старшее (сегмент)
pop es
push ds

;изменение вектора
mov cx, cs
mov ds, cx
lea dx, cs:maspr
mov ah,25h
mov al,69h
int 21h
pop ds    

;входные параметры процедуры    
mov cx,10
lea si, ds:mass1
lea di, es:mass2
;вызовем резидентный обработчик прерывания
int 69h

;восстановим старый обработчик прерывания
mov dx,word ptr ds:vect
mov ds, word ptr ds:vect+2
mov ah, 25h
mov al,69h
int 21h

;завершение исполнения
mov ah, 4ch    
int 21h

;объявление поцедуры
maspr proc
cycl: cmp byte ptr ds:[si], 0
jl m1
movsb
jmp m2
m1:inc si
m2:loop cycl
iret    
maspr endp
cseg ends
end code

Автор: R71MT 20.9.2015, 21:08
...процедуры не интересны! Интересно, что вектор потом восстановил! 

Автор: R71MT 25.9.2015, 20:39
Можно просто проверить старшую единицу каждого элемента..
На FASM'e это выглядит так (без сохранения/востановления вектора):
Код

USE16
ORG 100h
JMP start

hello   DB   'НАЙДЕНО ЭЛЕМЕНТОВ: $'
mass1   DB   1,-20,30,40,-30,-50,40,100,-45,2
leght   DB   0                   ; счётчик найденных элементов

start:
  PUSH  DS
  MOV   AX,2580h                 ; свой обработчик на INT-80h
  MOV   DX,new_80
  INT   21h
  POP   DS

  MOV   SI,mass1                 ; SI = адрес массива
  MOV   CX,10                    ; CX = его длинна
  INT   80h         ;<===========; зовём свой обработчик! =========================//

  MOV   AH,9                     ; выводим мессагу юзеру
  MOV   DX,hello
  INT   21h

  MOV   AL,[leght]               ; AL = счётчик положительных элементов массива
  ADD   AL,30h                   ; переводим значение в ASCII-символ
  INT   29h                      ; выводим его на экран

  XOR   AX,AX                    ; ждём клавишу..
  INT   16h
  RET                            ; ..и на выход!

;//============ ОБРАБОТЧИК INT-80h ================================================//
new_80:
  LODSB                          ; берём символ из DS:SI
  TEST  AL,80h                   ; проверяем старшую единицу (80h = 1000 0000b)
  JZ    next                     ; если нуль - число положительное!
  LOOP  new_80                   ; значит единица. Берём следующий символ массива
next:
  INC   BYTE[leght]              ; увеличиваем счётчик,
  LOOP  new_80                   ;        ..и мотаем цикл CX-раз.
  IRET                           ; возвращаем управление программе

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)