[comp.windows.ms] __ahincr

brianf@umd5.umd.edu (Brian Farmer) (07/14/90)

	Has anyone tried to use the predefined variable '__ahincr'.  We
have a program that works with bitmaps that are > 64k so it needs to
update the selector after passing the end of the segment but we can't
get __ahincr to work.  We are using MSC 6.0 with the 3.0 SDK.  The code
is written in C and in-line assembly.  The definitions we have used are

extern int __ahincr;   
extern int _ahincr;

The first definition gives an undefined external on linking.  The second
compiles and links correctly but on running has a value of zero.

The code the actually works with the segments is in-line code.


Thanks for any help you might be able to offer.

Brian Farmer
brianf@umd5.umd.edu

kensy@microsoft.UUCP (Ken SYKES) (07/17/90)

In article <6887@umd5.umd.edu> brianf@umd5.umd.edu (Brian Farmer) writes:
>
>	Has anyone tried to use the predefined variable '__ahincr'.  We
[stuff deleted]
>
>extern int __ahincr;   
>extern int _ahincr;
>
>The first definition gives an undefined external on linking.  The second
>compiles and links correctly but on running has a value of zero.
>
>The code the actually works with the segments is in-line code.
>
>
>Thanks for any help you might be able to offer.
>
>Brian Farmer
>brianf@umd5.umd.edu

_ahincr is an absolute external which means that the value you want 
is actually the address of the variable, not the contents.  What you
should do is the following:

extern int _ahincr;

#define AHINCR &_ahincr

in your code do

seg += AHINCR;

in assembler you would define the symbol as absolute external and everything
would be fine.  For the in-line assembler you may have to do the following:

int ahincr = &_ahincr;

and use ahincr in your in-line assembler (There may be an easier way...)

Hope this helps.

--Ken Sykes
The opinions expressed are mine and don't represent my Employer's.

michaelt@microsoft.UUCP (Michael THURLKILL) (07/17/90)

In article <55849@microsoft.UUCP> kensy@microsoft.UUCP (Ken SYKES) writes:
>In article <6887@umd5.umd.edu> brianf@umd5.umd.edu (Brian Farmer) writes:
>>
>>	Has anyone tried to use the predefined variable '__ahincr'.  We
>
>_ahincr is an absolute external which means that the value you want 
>is actually the address of the variable, not the contents.  What you
>should do is the following:
>
Also remember, if you are writing in C, you shouldn't normally need
to use __ahincr directly. If you declare your pointers as HUGE, the
C compiler will generate the necessary code for you (by using __ahincr).
You would have to use __ahincr directly if you are doing something
other than 'normal' huge pointer manipulation, or in your case, useing inline 
assembler. In that case, you would need to take the address as 
described previously. 

Also for an example of using __ahincr, write some code that uses
huge pointers and steps through a >64k array. Generate an assembler
listing with the /Fa switch from the compiler, or look at the code
in assembler mode in codeview.

Mike Thurlkill
 
Disclaimer: These are my opinions. They should not be misconstrued
as being correct or as having any relation to my employer.

mms00786@uxa.cso.uiuc.edu (07/18/90)

Can someone please clarify the following :

Under enhanced and standard mode, I am now allowed to GlobalAlloc chunks greater
than 64K. I assume I am also able to GlobalLock these large chunks. Question is,
how do I access this memory? For example, suppose I wanted to create a memory
chunk filled with letter 'a', would the following work?

  hMem = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, 70000);
  lpStr = GlobalLock (hMem);
  for (i=0; i < 70000; i++)
      *lpStr++ = 'a';

  /* what a useful code segment! */


Or would I have to worry about segment boundaries etc, possibly through
the use of this mysterious _ahincr?

Milan
.

brianf@umd5.umd.edu (Brian Farmer) (07/18/90)

In article <118500044@uxa.cso.uiuc.edu> mms00786@uxa.cso.uiuc.edu writes:

>Under enhanced and standard mode, I am now allowed to GlobalAlloc chunks greater
>than 64K. I assume I am also able to GlobalLock these large chunks. Question is,
>how do I access this memory? For example, suppose I wanted to create a memory
>chunk filled with letter 'a', would the following work?
>
>  hMem = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, 70000);
>  lpStr = GlobalLock (hMem);
>  for (i=0; i < 70000; i++)
>      *lpStr++ = 'a';
>

Only if lpStr is a huge pointer.


>Or would I have to worry about segment boundaries etc, possibly through
>the use of this mysterious _ahincr?

Only if lpStr is just a long pointer.  I wanted to know about is because
we have a routine needs to be as quick as possible so was written in 
in-line assembly.  Here is a routine that I wrote to test __ahincr that
should do what you want.  A huge pointer is easier for C.

/*  __ahincr needs to be define like:       */

extern	int	_ahincr;



void AhincrTest (HWND hWnd)

{
        HANDLE  foo;
        char    far *foo2;
        int     incr, *ptr;
        LONG    i;


	incr = &_incr;

        foo = GlobalAlloc (GMEM_MOVEABLE, 70000);
        foo2 = (char far *)GlobalLock (foo);

        incr = &_ahincr;

        ptr = (int *)&foo2;

        while (i<70000)
        {
                foo2[(int)i] = 'a';  /* (int)i or LOWORD (i) should work here */
                i++;
                if (!LOWORD (i))
                        ptr[1] += incr;  /* update the segment pointer. 
					    you can also use __ahincr for
					    subtraction to go backward in 
					    array.		       */
			

        }

	GlobalUnlock (foo);

        MessageBox (hWnd, "finished looping", "Generic.C", MB_OK);
}


Thanks to Microsoft for posting there earlier responses, they really helped.


Brian Farmer 
brianf@umd5.umd.edu

matts@microsoft.UUCP (Matt SAETTLER) (07/21/90)

In article <118500044@uxa.cso.uiuc.edu> mms00786@uxa.cso.uiuc.edu writes:
>
[...]
>how do I access this memory? For example, suppose I wanted to create a memory
>chunk filled with letter 'a', would the following work?
>
>  hMem = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, 70000);
>  lpStr = GlobalLock (hMem);
>  for (i=0; i < 70000; i++)
>      *lpStr++ = 'a';
>
>  /* what a useful code segment! */
>
>
>Or would I have to worry about segment boundaries etc, possibly through
>the use of this mysterious _ahincr?

(assuming Microsoft C, of course)

This will work, assuming you have defined lpStr as

char huge * lpStr;

The C compiler automatically generates the correct code to use _ahincr
WHEN variables are defined as huge (as opposed to far).

In other words, this will NOT work for moving through >64k:

char far * lpStr;	
	...which is the same as...	
LPSTR lpStr;

(and, as used here, i must be a DWORD or long or something big enough
to handle numbers > 65535 )

---------------------
I speak only for myself, or so I'm told to say.