Further information about 64 bit FTN95

Programs compiled with FTN95 using the /64 option, use the AMD64 instruction set (subsequently adopted by Intel, and referred to as x64 or x86_64) which is almost universally available on modern PC's. This code cannot be mixed with legacy 32-bit code, nor can it access legacy 32-bit DLL's. 64-bit object files must be linked using the new utility SLINK64. This object file format is incompatible with all third-party link utilities.

The default size of INTEGER variables remains unchanged (231-1), so INTEGER*8 (8-byte) variables must be used to index extremely large arrays. These variables are implemented in a more efficient and natural way in 64 bits. Note that some arrays that would not fit in the old 4GB limit may still be indexable using default sized integers, for example a REAL*8 array of 2,000,000,000 elements would occupy nearly 16GB of memory, but could be indexed using default integers.

The main value of 64-bit compilation is that the available address space has increased from 4GB to approximately 1.8 x 1019 bytes. This means that for the foreseeable future (possibly forever), the size of programs will be limited only by the amount of physical memory available on a system.

Arrays that are ALLOCATEd, or which are in COMMON or in MODULEs can exceed the 4GB limit, except that initialised arrays must fit within the .EXE or .DLL file to which they belong, and the the size of these files cannot extend beyond the 4GB limit. This is a Microsoft limit, but is fairly reasonable, since the time needed to load a 4GB file would be excessive.

COMMON blocks and MODULE arrays are allocated dynamically as a program starts in order to enjoy no 4GB restrictions. This is applied to all such storage blocks, because a program may exceed the 4GB limit even though each individual array lies within this limit.

Local arrays are placed on the stack and the default size of this stack is currently 32MB. This size can be adjusted without limit via a command to the linker (SLINK64). Alternatively, users who require a very large local array, can use a COMMON block or MODULE or change to an ALLOCATABLE array.

Variables with the SAVE attribute are currently limited to a total of 1GB of memory. SAVEd variable that are initialised are packed into the EXE or DLL file to which they belong. Since the code can be distributed across multiple DLL's plus an EXE file, the code itself is also not limited to 4GB - although this is not usually a serious concern.

The various 64-bit Windows operating systems provide less than the full 1.8 x 1019 address space, and the size of this space varies somewhat with the available physical memory on the system. Nevertheless, these limits are very generous and will increase as physical memory becomes more plentiful. In part, these limits are due to the fact that the paging mechanism itself requires memory.
For further information see...

The pair of 64 bit DLLs, SALFLIBC64.DLL and CLEARWIN64.DLL take the place of the 32 bit SALFLIBC.DLL. Currently CLEARWIN64.DLL (which contains much more than ClearWin+) is compiled with Microsoft C++. In the future this may be absorbed into SALFLIBC64.DLL but will remain independent for use with third-party compilers.

Perhaps surprisingly, FTN95.exe and SLINK64.exe are 32-bit executables, and so still require access to SALFLIBC.DLL at compile time.

Note that the extra executables and DLL's that support 64-bit mode can coexist with those that support 32-bit operations because they have different names.


  INTEGER n,localA(1000)
  INTEGER automaticA(n)
  automaticA(1) = 42
PROGRAM arraytest
  CALL sub1(1000)

Compile this sample with the options /64 /EXPLIST and examine the resulting .lis file.

Local array localA

On entry to sub1, the assembly instruction "SUB_Q RSP,168" moves the "stack pointer" down the stack by an amount that depends on the size of the array localA. At the end of sub1 the instruction "ADD_Q RSP,168" moves the stack pointer back up the stack by the same amount. If there were to be a call to another routine sub2 within sub1 then the stack pointer would move further down the stack during the call to sub2 and so on.

The required stack size corresponds to the lowest point that is reached by the stack pointer for the various paths through your code.

SLINK64 provides for a default stack size of 32MB. This can be changed via the SLINK64 "stack_size" option where the value is input in hexadecimal form (so the default is 0x2000000). The original upper limit for this value was 4GB. But this limit was effectively removed at v8.50 of FTN95. SLINK64 constructs the header for your application and this conforms to the "Portable Executable" standard. SLINK64 simply uses the stack_size value to set the OptionalHeader.SizeOfStackReserve entry in the "MasterHeader" part.

SLINK64 can use "stack" as an alternative to "stack_size". "stack" takes a decimal value that is the required size in (decimal) megabytes (i.e. millions).

Automatic array automaticA

The allocation of memory for the automatic array autmaticA appears in the assembly instructions as a call to __alloc_pseudo_stack. This allocation operates via a separate stack (which for our purposes is called the "pseudo" stack).  The inverse operation is represented by a calls to __return_pseudo_stack_ptr and  __set_pseudo_stack_ptr. This "pseudo" stack is automatically initialised via a call to the Windows API function VirtualAlloc. The default size of this stack is half of the size of the available RAM less the size of your program code. This default value can be reduced by using the FTN95 command line option /VSTACK. VirualAlloc provides memory on demand (when committed). The reserved size that is used when initialising does not restrict the amount of RAM that is available for other purposes.

Dynamic array dynamicA

The allocation of memory for the dynamic array dyanamicA appears in the assembly instructions as a call to __ALLOCATE@. This function calls in turn upon the Windows API function HeapAlloc in order to allocate memory from the Windows OS heap. FTN95/SLINK64 provide no limit to the amount of dynamic memory that can be allocated.

Note that the performance on your application might depend on factors such as the size of the available RAM. Using large amounts of memory can lead to the paging in and out of memory from a hard drive resulting in extremely poor response times.

Copyright © 1999-2024 Silverfrost Limited