From: gillmore@picard.slc.mentorg.com (Mike Gillmore (Consultant))
Subject: Re: ass'y gurus?
Reply-To: mike_gillmore@mentorg.com
Organization: Mentor Graphics Corp.,  Murray, Utah
Distribution: alt
Date: Wed, 2 Sep 1992 13:27:34 GMT

In article <1992Sep2.1937.412@dosgate>, "gord armstrong" <gord.armstrong@canrem.com> writes:
> 
> Segments ARRRG!
> 
> 'C' Compiler: Microsoft C 6.0, Assembler: TASM 2.0
> 
> I'm linking a 'C' and assembler prog together in DOS, and I need
> to pass a pointer from a C prog to an assembler proc. For a SMALL
> model this is not much of a problem since code and data are in the
> same segment, as follows:
> 
>   char *ptr; // will use in other modules, make it global
> 
> main()
> {
>   ptr=malloc((unsigned int)1024); *ptr=0x55;
>   get_value();  // call ass'y routine
>   free(ptr);
> }
> 
> 
> DOSSEG
> .MODEL SMALL
>                 public  _get_value:proc
> .DATA
>                 extrn   _ptr:word
> other_var       db  ?
> .CODE
> ;--------------------------------------------------------
> ; _get_value
> ;--------------------------------------------------------
> _get_value      proc
>                 procin              ;save stuff for 'C'
>                 mov     bx,word ptr _ptr
>                 mov     al,[bx]
>                 xor     ah,ah
>                 call    to_integer  ;get '55' as set in main()
>                 procout             ;restore stuff for 'C'
>                 ret
> _get_value      endp
> 
> For a LARGE model, I can't seem to find a way or a keyword to
> do it neatly. A 'malloc' in the large model has 'ptr' pointing
> to another segment. I can make it work doing the following:
> 
>   char far *_ptr;
>   unsigned int ptr_seg,ptr_off;
> 
> main()
> {
>   ptr=malloc((unsigned int)1024); *ptr=0x55;
> 
>   ptr_seg=FP_SEG(ptr); ptr_off=FP_OFF(ptr);
> 
>   get_value();  // call ass'y routine
>   free(ptr);
> }
> 
> DOSSEG
> .MODEL LARGE
>                 public  _get_value:proc
> .FARDATA
>                 extrn   _ptr_seg:word
>                 extrn   _ptr_off:word
> .DATA
> other_var       db  ?
> .CODE
> ;--------------------------------------------------------
> ; _get_value
> ;--------------------------------------------------------
> _get_value      proc
>                 procin                ;save stuff for 'C'
>                 assume  ds:@FARDATA   ;FAR for large model
>                 mov     ax,@FARDATA
>                 mov     ds,ax         ;...is now our DS
>                 mov     es,_ptr_seg
>                 mov     bx,_ptr_off
> 
>                 assume  ds:@DATA      ;put back DS for 'other_var'
>                 mov     ax,@DATA
>                 mov     ds,ax
> 
>                 mov     al,es:[bx]    ;get '55' as set in main()
>                 xor     ah,ah
>                 call    to_integer
>                 procout             ;restore stuff for 'C'
>                 ret
> _get_value      endp
> 
> It works, but it looks messy, is there a neater way of doing this?
> If I use OS/2, I won't have this problem since it uses protected
> mode...right?
> 
> All help appreciated!
> ---------------------------------------------------------------------
> gord.armstrong@canremote.com   "If you blow chunks and she comes
>                                 back, she's yours. If you spew and
>                                 she bolts, it was never meant to be"
>                                 - Wayne's World
> --
> Canada Remote Systems  - Toronto, Ontario/Detroit, MI
> World's Largest PCBOARD System - 416-629-7000/629-7044


	I think that it makes more sense to pass the data
on the stack.

	In C:

	get_value(char * ptr);

	In ASM:

	StackFrame	Struc
		Old_Frame	Dw	?
		RtnAddr		Dd	?	; Segment and offset
		CharPtr		Dd	?	; Segment and offset
	StackFrame	Ends
		
	_get_value	Proc	Far
		Push	Bp
		Mov	Bp, Sp
		Les	Si, Bp.CharPtr
		Mov	Al, Es:Si
		Xor	Ah, Ah
		Call	to_integer
		Pop	Bp
		Ret	(Size StackFrame)-(Size RtnAddr)-(Size OldFrame)
	_get_value	Endp

	The beauty of this method is that to change memory models,
	remember that small has short pointers (offset only), and
	near procedures (RtnAddr is Dw), medium has a mixture of
	code and data, large has far code and data, which requires only
	a change to:
		RtnAddr		Dd	?
				^^	becomes Dw

		_get_value	Proc	Far
					^^^	becomes Near

		Les	Si, Bp.CharPtr
		^^^	becomes Mov



-- 
Mike "Okie" Gillmore
no .sig, no glory
Newsgroups: alt.lang.asm