Quote
In article <23MAR96.11871364.0...@music.mus.polymtl.ca> Zikovsky wrote:
>Date: 23 MAR 96 10:59:31 EST
>From: Zikovsky <Z...@music.mus.polymtl.ca>
>Sender: use...@music.mus.polymtl.ca
>Newsgroups: comp.lang.pascal.borland,comp.lang.pascal.misc
>Subject: Calling procedures in inline assembler : HELP NEEDED!
>Hello everybody!
> I'm programming using the inline assembler of Turbo Pascal 7.0.
>I am writing a SVGA sprite writing routine, and I need to switch
>banks at some point. I have a procedure called SetBank(Bank:word)
>that works fine, but I can't call it in assembler because I don't
>know how to give the parameters. So I tried putting my parameter in
>a global variable, and calling an other bank switching routine with
>no parameters but that uses that variable. It doesn't seem to be
>able to switch the bank properly.
> Is there anything i'm missing? Should there be special lines before
>and after the CALL? Note that I'm accessing a pointer that contains
>the data of the sprite. Does that change something?
>The code looks a little like this :
>Asm
> Push DS
>lds si,[sprite] {sprite is the pointer to an array}
> mov ax,$a000
> mov es,ax
>{Etc... I use lodsb to load from the array and [ES:DI] to put in
>video memory. Then I need to switch banks to 1, for example :}
> mov [Bank2Set],1
> Call SetTheBank {SetThebank uses Bank2Set as the number of the bank}
>{Continue drawing ....}
> Pop ds
>end;
>Can anyone help me? Please E-Mail me at z...@music.mus.polymtl.ca.
I don't know what "SetTheBank" looks like, but I will assume it is a Pascal
procedure. For starters, you probably need to save your working registers
and restore the environment before making the call and then restore your
parameters and working environment when it returns. The second thing is to
push SetTheBank's parameters onto the stack.
push DS; push SI { save sprite }
push ES { save video segment }
mov AX,SEG @DATA; mov DS,AX { Restore DS/DATA segment }
push [Bank2Set] { or use mov AX,1; push AX }
call SetTheBank
pop ES { Restore video segment }
pop SI; pop DS { Restore sprite }
Note that the bank parameter was not removed from the stack. In Pascal, it is
the responsibility of the called routine to remove it's parameters. In this
case, SetTheBank would "pop" the word parameter before it returned.
If you know where in relation to BP the DS register was pushed, you could use
something like mov DS,[BP-PushedDS] to retrieve it. This of course requires
that the routine we are in to have formal parameters or local variables that
would cause the compiler to generate the necessary code to implement a stack
frame. Another, somewhat safer method is to declare a local variable and
store and restore DS from it.
VAR DSreg: Word;
Begin
mov [DSreg],DS
--- do your thing ---
mov DS,[DSreg]
--- some more from above ---
mov DS,[DSreg]
End;
Doing anything less than saving your work register and restoring DS/BP before
calling another routine should be done only because you have an intimate
knowledge of the inner workings of the called routine. In which case you
should also insure the called routine has comments describing which registers
it _must_ preserve, and things that it doesn't care about or are considered
normal or standard practice. If you have any type of error checking enabled,
yuu'd best think twice before calling another routine without having DS
properly set.
...red