hi,i'm trying to modify the interruption 23h but my code don't do what i want and i can't find the error
here is my code
Title interruption23h

redirige_int macro
mov ah,35h
mov al,23h
int 21h
mov ,bx
mov ,es

mov ah,25h
mov al,num_int
mov dx,offset traiter_ctrl_break
int 21h
traiter_ctrl_break:
mov ah,9
mov dx,offset msg2
int 21h
verif1:
mov ah,1
int 21h
cmp al,'o'
jne verif2
jmp fin_propre
verif2:
mov ah,1
int 21h
cmp al,'n'
jne verif1
jmp afficher_bonjour
fin_propre:
mov ds,offset retour
mov al,num_int
mov ah,25h
int 21h
retour:
mov bx,
mov es,
endm

.model small
.stack 100h
.386
.data
v dw 32000
vecteur dw ?
msg1 db 10,13,"bonjour$"
msg2 db 10,13,"souhaitez vous vraiment fermer le programme?(o/n)$"
num_int db "23h"

.code
main proc
mov dx,@data
mov ds,dx
mov cx,0
afficher_bonjour:
mov ah,9
mov dx,offset msg1
int 21h
inc cx
cmp cx,v
jne afficher_bonjour
redirige_int

mov ah,4ch
int 21h
main endp
end main
Posted on 2011-01-05 14:11:30 by marooh
As a general rule, when you ask, "Why doesn't my code work?" it is helpful to tell us what you "intend" for the code to do, and what it actually does.

From what I can see, you say "bonjour" 32000 times, do your macro, and exit the program. It looks to me like it should get as far as the macro... and then, I dunno. I don't know why you put this stuff in a macro, but...


redirige_int macro
mov ah,35h
mov al,23h
int 21h
mov ,bx
mov ,es

mov ah,25h
mov al,num_int
mov dx,offset traiter_ctrl_break
int 21h
...


First, you get the old handler, and save its address. Good, but you only reserve one word for "vecteur", so the "" is going to clobber something else. Since it's the first two bytes of "bonjour", which we're done printing, this isn't going to do any harm, but it's "wrong". (just reserve two bytes for "vecteur" to fix it).

Then, you set a new interrupt handler, the one in al... but look at the data declaration:


num_int db "23h"


By putting the quote marks around this, you make it a text string, so when you load al from it, you get the character '2' - 32h. This is not the interrupt you intend to replace! (just remove the quote marks to fix it)

int 21h/25h expects the new interrupt handler's address in ds:dx. You've got dx right, but your new handler is in the code segment, and ds is still pointed at the data segment.

Then you "fall through" into your proposed new handler. I doubt if that's what you want to do. Using dos interrupts within another interrupt handler is generally a bad idea. It can be made to work, but you don't need complications. As a "first test" of your new handler, I'd suggest something that doesn't need any interrupts. Do you know how to put an 'X' on the screen "direct to video memory"? Try that first, and when it works, ease up to something more complicated.

At the end of an interrupt handler, you may need to acknowledge the interrupt - send an EOI (end of interrupt) to the PIC (programmable interrupt controller) - port 20h, if I remember correctly, and maybe port 70h, too((?). A common way to deal with this "housekeeping" is to jump into the old interrupt handler after you've done "your stuff". You've saved the address in "vecteur" (two words, right?), so just do a far jump to it. I'm not sure what the Masm syntax would be...

Also, you probably want to preserve any registers you alter in your interrupt service routine - the interrupted program is using them!

One last complaint:


fin_propre:
mov ds,offset retour


Is this a legal instruction? What is the purpose?

Mmmm, it occurs to me that Randy Hyde's old 16-bit Art of Assembly book must have an example of an ISR...

http://www.arl.wustl.edu/~lockwood/class/cs306/books/artofasm/Chapter_17/CH17-1.html#HEADING1-7

See if you can get some help from that. Start with something simple!

Best,
Frank

Posted on 2011-01-07 09:07:50 by fbkotler
thank you very much for your help,i modified my source code and i hope this time it is correct.
the purpose of this program is to modify the interruption 23h and change her with a question "would you leave this program y or n?"
if the user answer is yes,this program (to display "bonjour" 32000 times) will shut down else this program will continue displaying.
here is my new code:
Title interruption23h 

redirige_int macro
mov ah,35h
mov al,23h
int 21h
mov ,bx
mov ,es
mov dx,seg traiter_ctrl_break
mov ds,dx
mov ah,25h
mov al,num_int
lea dx,traiter_ctrl_break
int 21h
traiter_ctrl_break:
mov ah,9
mov dx,offset msg2
int 21h
verif1:
mov ah,1
int 21h
cmp al,'o'
jne verif2
jmp fin_propre
verif2:
mov ah,1
int 21h
cmp al,'n'
jne verif1
jmp afficher_bonjour
fin_propre:
mov bx,
mov es,
mov al,20h
out 20h,al ;End Of Interrupt
popad
iret
endm

.model small
.stack 100h
.386
.data
v dw 32000
vecteur word
msg1 db 10,13,"bonjour$"
msg2 db 10,13,"souhaitez vous vraiment fermer le programme?(o/n)$"
num_int db 23h

.code
main proc
mov dx,@data
mov ds,dx
mov cx,0
afficher_bonjour:
mov ah,9
mov dx,offset msg1
int 21h
inc cx
cmp cx,v
jne afficher_bonjour
redirige_int

mov ah,4ch
int 21h
main endp
end main
Posted on 2011-01-07 11:39:08 by marooh
The "popad" might be a good idea, but don't you think you should "pushad" first?

Best,
Frank

Posted on 2011-01-07 13:38:27 by fbkotler
where i can put pushad?? and there isn't any other error??
thank you :)
Posted on 2011-01-07 15:07:11 by marooh

where i can put pushad??


At the beginning of your ISR, I suppose. I don't know why you're using 32-bit instructions here, but I don't think it'll do any harm. Keep in mind that pusha/popa (or pushad/popad) save and restore only the general purpose registers. If you alter segment registers (which you do), you'll want to save/restore them, too.


and there isn't any other error??


I didn't say that!

I'm not familiar with Masm syntax. Does:


vecteur word


reserve two words? It doesn't look like it!

You still print "bonjour" 32000 times, and then replace the control-break handler. You then "fall through" and execute the "ISR code" whether an interrupt has occured or not. You print a message using a dos interrupt (which probably isn't going to work - see the "indos flag"), then wait for a key (again using a dos interrupt). If the user doesn't reply "oui", you wait for another key! If it's 'n', you go back to printing "bonjour". When/if the 32000 displays finishes, you go back into the macro, attempting to install your ISR again (this time, the "old" vecteur will be your "new" ISR). When/if the user finally presses 'o', you load bx and es from "vecteur", acknowledge an interrupt that hasn't happened, restore GP registers (which we'll assume you've pushed) - thus undoing what you just did to bx (but leaving es in an altered state). Then you "iret" from an interrupt that hasn't happened. If you ever got out of the macro, you'd exit from the program, leaving the IVT in an altered state (but taking away the code that you've pointed it to). You want to either restore the original interrupt vector, or leave your new ISR in place by "terminate and stay resident" instead of a normal exit. I don't see how this is going to do anything useful.


thank you :)


Don't thank me, Dude! I'm telling you you don't know enough to tackle an ISR! If this is "homework", I suppose you've got no choice, but if not, practice on some "regular" programs first. (if it's homework, it's a horrible assignment, IMO - I'll bet nobody gets it right!). In addition to Randy's book which I mentioned (you may want to start earlier than the ISR chapter) there's some information from Ben Lunt:

http://www.frontiernet.net/~fys/tsrdemo.htm

Don't feel bad about this - nobody is born knowing this stuff! As you can see, it's pretty complicated - not a good "beginner exercise" at all. I don't entirely agree that "dos is dead", but it's "in intensive care" (maybe "hospice care"). I question whether learning this much about dos is worth your time. None of this will work on a "modern OS". If you must, "hang in there" and you'll get it eventually, but I think you've got a long way to go! Courage!

Best,
Frank

Posted on 2011-01-08 01:54:52 by fbkotler
hi again,thx for your time
yes it is a project i need to do and unfortunatly i will not :(
i'm new in this language and it's very hard for me to deal with this project,i already spent 2 weeks and no result as you can see.if you could specify the exact wrong instr so i will try to fix it will be generous from you
Posted on 2011-01-08 16:34:43 by marooh
It's a hard project! It isn't a case of "wrong instruction", it's a case of "wrong logic". What you actually do is print "bonjour" 32000 times, and then hook the control-break interrupt. This isn't going to do anything useful. Replacing the control-break handler first, and then printing "bonjour" 32000 times would at least give you a chance to hit control-break... but still not very useful. If you were to replace the control-break handler and leave it there ("terminate and stay resident" instead of "exit" - your new handler code needs to stay in memory!), then you could run any program - perhaps one to print "bonjour" - and if you hit control-break, you'd be asked if you really wanted to quit or continue. That might be somewhat "useful" (a little).

I sometimes suggest, if you don't know how to do a program, to write the comments first. But you can't even do that, without a clear "specification". Exactly what is this program required to do?


; make sure we haven't already been installed?
; get the original vector and save it
; install the new vector
; print "bonjour" 32000 times (why not forever?)
; re-install the original saved handler
; exit

; this is code that is executed if "control-break" hit while printing

new_handler:
; save registers
; pretend we can use dos interrupts - difficult! Much more code here!
; ask user
; if "Oui", we want to quit
; restore registers
; jump to the original saved vector
; if "Non", we want to continue
; restore registers
; acknowledge interrupt (EOI)
; iret


Maybe we want to do the EOI before we restore registers. That's just a very rough first draft. Is that approximately what you want to do? Or do you want to leave the new handler in memory? If so, do you need to be able to remove it?

Does your "project" actually require that you use dos interrupts within your interrupt handler? We could put "the question" on the screen without 'em. Maybe the bios int 16h would be easier to use in a handler than the dos interrupt, to get the 'o' ou 'n'. I'm not sure. I'm sure using dos interrupts is going to be tough! I think we have to...


; find the "indos" flag
; check the "indos"  flag
; if set (we're "indos")
; I dunno, check it again until it's clear?
; if clear...
; check to see if we're in the "critical error handler"
; (not sure how to do that)
; if so... wait?
; if not ...
mov dx, offset msg2
mov ah, 9
int 21h
; etc...


Now where you currently go from there might be a good "something simple" to start with.


; print "bonjour" a few times, if you like
; print your "question"

verif1:
mov ah,1
int 21h
cmp al,'o'
jne verif2
jmp fin_propre
verif2:
mov ah,1
int 21h
cmp al,'n'
jne verif1
jmp afficher_bonjour
fin_propre:
; exit
...
afficher_bonjour:
; print "bonjour" a few more times
; exit


In a real interrupt handler, you wouldn't want to jump back into the interrupted program to "continue" - when the interrupt is done (iret), the interrupted program continues from where it left off, unless you've terminated it as the original control-break handler does...

But forget about installing new interrupt handlers for now, just write it as a regular program. You've got one too many int 21h's in there. Clean up that logic, first.

Then, before you put it back into an interrupt handler, try a simpler interrupt handler. Your code to install the handler looks pretty good, try installing something that doesn't use dos interrupts.


new_handler:
  push es
  push 0B800h
  pop es
; put an 'X' at row 10, column 10
  mov byte ptr es:[(80 * 10 + 10) * 2], 'X'
  pop es
  push ax
  mov al, 20h
  out 20h, al
  pop ax
  iret


I'm not sure that's right. Maybe it would be simpler to jump to the original saved interrupt and let it terminate... but with an 'X' on the screen... if it worked. If you can get that to work, start thinking about using dos interrupts in your handler. Read and re-read Randy's chapter on it, and Ben's examples, and anything else you can find on the subject. It's a hard project!

Best,
Frank




Posted on 2011-01-09 10:54:14 by fbkotler
hi again and thx for your advices,
i tried to write a code that displays x on the screen like you said when ctrl break is pushed,
here is the code:

.model small
.stack 100h

.data
intvectsave dw 00h,00h

msg1 db 10,13,"bonjour$"

.code
start:  jmp short install
OurISR:
push es
push 0B800h
pop es
mov byte ptr es:[(80 * 10 + 10) * 2], 'X'
mov al, 20h
out 20h, al
popa
iret 


install:

mov    ax, 3523h
int    21h
mov    word ptr IntVectSave, bx
mov    word ptr IntVectSave+2, es
mov    dx, seg OurISR
mov    ds, dx
lea    dx,OurISR
mov    ax, 2523h 
int    21h
jmp aff
   

aff:
mov dx,@data
mov ds,dx
mov cx,0
afficher_bonjour:
mov ah,9
mov dx,offset msg1
int 21h
inc cx
cmp cx,32000
jne afficher_bonjour
lds    bx, IntVectSave
mov    ax, 2523h

int    21h

is it wright??
Posted on 2011-01-09 16:22:02 by marooh
Much, much closer!


.model small
.stack 100h

.data
intvectsave dw 00h,00h ; two words, good!

msg1 db 10,13,"bonjour$"

.code
start:  jmp short install
OurISR:
pusha ; added
push es ; save original segment

; change es to video memory

; could do instead:
; mov ax, 0B800h
; mov es, ax

push 0B800h
pop es

mov byte ptr es:[(80 * 10 + 10) * 2], 'X'

; acknowledge interrupt
mov al, 20h
out 20h, al

pop es
popa
iret 


install:

; we need to do this first - the "save" uses ds!
mov dx,@data
mov ds,dx

mov    ax, 3523h
int    21h
mov    word ptr IntVectSave, bx
mov    word ptr IntVectSave+2, es
mov    dx, seg OurISR
mov    ds, dx
lea    dx,OurISR
mov    ax, 2523h 
int    21h
jmp aff
   

aff:
;mov dx,@data ; already done above
;mov ds,dx

mov cx,0
afficher_bonjour:
mov ah,9
mov dx,offset msg1
int 21h
inc cx
cmp cx,32000
jne afficher_bonjour


; restore original ISR
;lds    bx, IntVectSave
lds    dx, IntVectSave ; don't we want dx here?
mov    ax, 2523h
int    21h

; exit
mov ax, 4C00h
int 21h

end start ; to tell Masm our entrypoint?



Good job! No guarantee that this is actually going to work, but it's what I had in mind for "try something simpler first"!

Does it work? Our 'X" is going to scroll off the screen pretty quick, so watch closely!

Best,
Frank

Posted on 2011-01-10 08:07:56 by fbkotler
hi again,
thx for your support. i tried to eexecute this code but i found out that my processor cannot handle popa,pusha and lds!!!  :sad: how can i remplace them??
and how can i now put my first handler??
Posted on 2011-01-10 10:58:27 by marooh
How do you determine that your processor can't handle pusha, popa, and lds? AFAIK, lds has been around since 8086, pusha and popa were apparently introduced in 80186. I've been assuming we're talking about something in the x86 family...

If you needed to, you could push/pop just the registers you actually alter, and load ds and dx separately, but I can't imagine that's necessary. If it's Masm that's having a problem, not your processor, a ".186" directive might fix it(?).

Best,
Frank

Posted on 2011-01-10 11:42:20 by fbkotler
hi again,
i got it.the result was strange!!  :shock:
it displays "bonjour" with a list of diffrent symbols(heart,as etc)
and ctrl break don't do anything  :sad:
Posted on 2011-01-11 04:37:03 by marooh
Well, I guess a strange result is better than no result at all. "Progress" of a sort. The fact that control-break doesn't do anything indicates that you've got it replaced. As I mentioned, the 'X' (if it appears at all) would scroll up off the screen pretty quick - could you be missing it? The "different symbols" are a puzzle! Does the computer behave normally (including control-break) after the program exits? That would indicate that you've replaced the original vector correctly. Not a bad start, despite the fact that is isn't close to what you want.

I don't know what to tell you, Marooh, except to keep reading, and keep trying stuff. It's a hard project!

Best,
Frank

Posted on 2011-01-11 06:06:14 by fbkotler
hi,
ok i will figure out a solution but could you explain me more about how can i write my first handler(displaying msg etc) because the last time there was many terms that i don't know so i don't know how to use
Posted on 2011-01-11 06:17:21 by marooh
I vaguely recall a file named "tbones" which explained how to use dos interrupts within an interrupt handler. I can't find a copy of it on my machine. This may be it:

http://code.filehungry.com/product/languages/assembler/x86_programming/sourcecode/various_sourcecode/t-bones/

You might be better off following Ben Lunt's examples, linked above.

Best,
Frank

Posted on 2011-01-11 06:48:53 by fbkotler
the link you gave me is about creating our own interrupt not changing an existing interrupt
Posted on 2011-01-11 18:20:05 by marooh