kordova
asked on
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
.386
PUBLIC _DrawPixel
PUBLIC _ResetVideoMode
PUBLIC _SaveVideoMode
.data
BackBuffer db 64000 dup(?)
.code
_SaveVideoMode PROC near
ARG VideoMode:PTR BYTE
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
ret
_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
ret
_ResetVideoMode ENDP
_DrawPixel proc near
ARG X:WORD,Y:WORD,Color:BYTE
LOCAL DT:BYTE ; UNUSED AT PRESENT, WILL BE USED
; 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
popbp
ret
_DrawPixel endp
end
The pertinent sections of main:
.model small
.stack 100h
.386
EXTRN _SaveVideoMode:near
EXTRN _ResetVideoMode:near
EXTRN _DrawPixel:near
.data
VideoMode db ?
.code
;... 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.
UPDATE:
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).
At present I have the following three functions in a file that is assembled separately and then linked with my main file:
.model small
.386
PUBLIC _DrawPixel
PUBLIC _ResetVideoMode
PUBLIC _SaveVideoMode
.data
BackBuffer db 64000 dup(?)
.code
_SaveVideoMode PROC near
ARG VideoMode:PTR BYTE
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
ret
_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
ret
_ResetVideoMode ENDP
_DrawPixel proc near
ARG X:WORD,Y:WORD,Color:BYTE
LOCAL DT:BYTE ; UNUSED AT PRESENT, WILL BE USED
; 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
popbp
ret
_DrawPixel endp
end
The pertinent sections of main:
.model small
.stack 100h
.386
EXTRN _SaveVideoMode:near
EXTRN _ResetVideoMode:near
EXTRN _DrawPixel:near
.data
VideoMode db ?
.code
;... 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.
UPDATE:
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).
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
it's a x86 CPU restriction, there's no way to push just a byte. It's a hardware thing.
ASKER
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