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.