jackiw@cs.swarthmore.edu (Nick Jackiw) (06/29/90)
spellbinder@uwav1.u.washington.edu writes: > > Here is a compiler question for those programmers out in net-land. > > type ArrayRecord = record > arraySize : longint; > signal : array [ 0..1 ] of real; > end; > ArrayRecordPtr = ^ArrayRecord; > ArrayRecordHdl = ^ArrayRecordPtr; > > The procedure knows how much data there is by getting the arraySize variable. > > Now I'm writing this code in THINK Pascal version 2.03. It works fine when the > amount of memory dedicated to the signal array is less than 32K, but when it > gets bigger than this, then things start to mess up. So basically, for array > sizes less than 8K data points, everything's fine. My idea is that THINK Pascal > has a problem getting a value at an offset greater than 32K from the start > of the variable. I have verified my idea by changing signal to become > an array of double and an array of extended and each time the procedure > craps out when the data exceeds 32K. My feeling is that the compiler is not > generating the correct code to access values beyond 32K. > > My questions are this: > > 1) Is there another explanation for the problem? > > 2) Are there any work arounds in THINK Pascal version 2.03? > > 3) Will THINK Pascal 3.01 avoid the problem? > > Thanks in advance. > > Blair Zajac Zajac@phast.phys.washington.edu Your diagnosis is correct: Pascal uses the 68K's "Address Register Indirect With Displacement" addressing mode to access array data, and this mode's displacement (the offset) is limited to a sign- extended 16-bit displacement integer. Thus, you're limited to 32K arrays. [A side note: in that it's sign-extended, it'd be possible to access 64K worth of data, if your base address was the arrayStart+32K, I think. Not that any Pascal compiler I've seen does this, of course...] The work around is the same for THINK 2 and 3--you'll have to calculate your own offset. The best way to do this is with a bit of inline assembler: type RealPtr=^real; function MyData(Where:ArrayRecordHdl; Index:integer):realPtr; inline $3017, $c0fc, $0004, $206f, $0002, $2050, $d1c0, $2f48, $0006, $5c4f; To access your data, where formerly you used ArrayRecordHdl^^[50] now use MyData(ArrayRecordHdl,50)^ Note that the third word of the in-line is $0004: this is the hardwired size of a single element of data in byte (1 REAL=4 bytes). The code compiles as: MOVE.W (A7),D0 ; Get the index off the stack MULU.W #4,D0 ; Multiply by the element size (32bit result) MOVEA.L 2(A7),A0 ; Get a handle to the array MOVEA.L (A0),A0 ; Dereference it ADDA.L D0,A0 ; Add it to the calculated offset MOVE.L A0,6(A7) ; Put resulting ptr back on the stack ADDQ.W #6,A7 ; and throw away arguments Be sure to change $0004 to SizeOf(elem) if your elements ever change from being real. This code generates is a bit less efficient than Pascal's native array indexing, but it gets you past the 32K problem. Note the complete lack of range checking...hope it's okay. -- --- jackiw@cs.swarthmore.edu | Smoggo: Can you prevent the detonation of jackiw@swarthmr.bitnet | the thermonuclear device? Applelink: D3717 | Jimbo: No ... I cannot.