Passing parameters and references in 16bit TASM

Posted on 2004-10-23
Last Modified: 2012-06-27
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).
Question by:kordova
    LVL 22

    Accepted Solution

    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.


    Author Comment

    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
    LVL 22

    Expert Comment

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


    Featured Post

    What Is Threat Intelligence?

    Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

    Join & Write a Comment

    Suggested Solutions

    PRTG Network Monitor lets you monitor your bandwidth usage, so you know who is using up your bandwidth, and what they're using it for.
    David Varnum recently wrote up his impressions of PRTG, based on a presentation by my colleague Christian at Tech Field Day at VMworld in Barcelona. Thanks David, for your detailed and honest evaluation!
    To add imagery to an HTML email signature, you have two options available to you. You can either add a logo/image by embedding it directly into the signature or hosting it externally and linking to it. The vast majority of email clients display l…
    In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor ( If you're interested in additional methods for monitoring bandwidt…

    732 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    17 Experts available now in Live!

    Get 1:1 Help Now