Passing parameters and references in 16bit TASM

I'm presently converting a simple 16bit TASM video mode 13h program to use the stack instead of globals and register passing to functions. I'm learning from a MASM book which may be the reason for some confusion on my behalf.

At present I have the following three functions in a file that is assembled separately and then linked with my main file:
.model small

PUBLIC _DrawPixel
PUBLIC _ResetVideoMode
PUBLIC _SaveVideoMode
BackBuffer db 64000 dup(?)
_SaveVideoMode PROC near
    push bp
      mov bp,sp

    mov ah,0Fh                       ; function 0Fh - get current mode
    int 10h                       ; Bios video service call
    mov BYTE PTR [VideoMode],al ; save current mode

    pop bp
_SaveVideoMode ENDP

_ResetVideoMode PROC near
ARG VideoMode:BYTE
; Resets the prior video mode (as stored in VideoMode) ; Originally a global
    push bp
      mov bp,sp

    mov al,VideoMode         ; set video mode 3, text
    xor ah,ah                   ; clear ah - set mode
    int 10h                   ; call bios service

    pop bp
_ResetVideoMode ENDP

_DrawPixel  proc near
; Plot Color at (X,Y)
    push bp
      mov bp,sp

    mov ax,320
    mul Y
    add ax,X
    mov di, OFFSET BackBuffer
    add di,ax
    mov al,Color
    mov [di],al

_DrawPixel  endp

The pertinent sections of main:
.model small
.stack 100h

EXTRN _SaveVideoMode:near
EXTRN _ResetVideoMode:near
EXTRN _DrawPixel:near
VideoMode  db ?
    ;... in main proc
    Call _SaveVideoMode C, offset VideoMode
    ; Set up timer etc

    Call _DrawPixel C, 160, 100, RED_INDEX   ; Draw red pixel in center of screen
    Call _FlipBuffer C  ; Show the change...

    Call _ResetVideoMode C,VideoMode
    ... etc

Now, I've used all of these functions successfully with globals and register passing, so I'm relatively sure that the logic is sound. However, it is evident from the results that none of the parameters passed are as expected...

What exactly am I doing wrong?

Thanks in advance for any help.

I've found in using the functions that if I use:
    mov ax,170
    mov bx,110
    Call _DrawPixel C, ax, bx, RED_INDEX

It works fine, though with:
    Call _DrawPixel C, WORD 170, WORD 110, RED_INDEX
it does not work as expected...

Isn't specifying an arg as a word the same as using a word register in the argument list?

Also, I seem to be getting functional behavior from the set/reset function when I set it as a word instead of a ptr byte in the argument list. (And I can't get it to pass as a byte at all, I'm getting the feeling that working with words works better...)

I'm still unsure as to what is wrong with the DrawPixel when I include the local variable (which I will need).
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

This is a very common problem.

You need to look at the generated code, either with a debugger or look at a full listing from TASM.

First see if the calling code is putting the parameters in the expected places.

Then see if the called code accesses the parameters correctly.


Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
kordovaAuthor Commented:
Ok, I looked through the .lst file (a first time for me, though it is quite helpful!) and I came upon the following:
    256      0088  B0 03                   mov al,3
    257                               Call _ResetVideoMode C,al
1   258      008A  50                       PUSH    AL
**Error** main.ASM(239)      CALLPROC(1) Argument to      operation or instruction has illegal size

I had been testing it with registers/immediates etc.

I'm getting the impression that the extended call is actually just a macro of some sort. Since it pushes all parameters on the stack, and evidently only words can be pushed onto the stack, are only parameters of word size allowed?

I must be missing something as that would force you to use your own macro to translate bytes into words when passing values, do that manually for every function call or limit yourself to words...

Thanks again
it's a x86 CPU restriction, there's no way to push just a byte.  It's a hardware thing.

It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.