Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > sci.space.policy > #56960 > unrolled thread
| Started by | JF Mezei <jfmezei.spamnot@vaxination.ca> |
|---|---|
| First post | 2016-07-10 12:43 -0400 |
| Last post | 2016-07-11 18:28 -0700 |
| Articles | 20 on this page of 52 — 7 participants |
Back to article view | Back to sci.space.policy
Apollo 11 source code released JF Mezei <jfmezei.spamnot@vaxination.ca> - 2016-07-10 12:43 -0400
Re: Apollo 11 source code released Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-10 20:33 +0300
Re: Apollo 11 source code released JF Mezei <jfmezei.spamnot@vaxination.ca> - 2016-07-10 18:28 -0400
Re: Apollo 11 source code released Jeff Findley <jfindley@cinci.nospam.rr.com> - 2016-07-10 21:27 -0400
Re: Apollo 11 source code released Fred J. McCall <fjmccall@gmail.com> - 2016-07-11 00:36 -0700
Re: Apollo 11 source code released Jeff Findley <jfindley@cinci.nospam.rr.com> - 2016-07-11 06:44 -0400
Re: Apollo 11 source code released Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-11 16:20 +0300
Re: Apollo 11 source code released Jeff Findley <jfindley@cinci.nospam.rr.com> - 2016-07-11 20:53 -0400
Re: Apollo 11 source code released JF Mezei <jfmezei.spamnot@vaxination.ca> - 2016-07-12 14:36 -0400
Re: Apollo 11 source code released Fred J. McCall <fjmccall@gmail.com> - 2016-07-12 18:11 -0700
Re: Apollo 11 source code released Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-12 23:37 +0300
Re: Apollo 11 source code released Fred J. McCall <fjmccall@gmail.com> - 2016-07-12 18:14 -0700
Re: Apollo 11 source code released Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-13 21:01 +0300
Re: Apollo 11 source code released Fred J. McCall <fjmccall@gmail.com> - 2016-07-13 20:06 -0700
Re: Apollo 11 source code released Jeff Findley <jfindley@cinci.nospam.rr.com> - 2016-07-14 06:44 -0400
Re: Apollo 11 source code released Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-15 23:54 +0300
Re: Apollo 11 source code released JF Mezei <jfmezei.spamnot@vaxination.ca> - 2016-07-17 11:49 -0400
Re: Apollo 11 source code released William Mook <mokmedical@gmail.com> - 2016-07-17 18:41 -0700
Re: Apollo 11 source code released Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-18 09:20 +0300
Re: Apollo 11 source code released JF Mezei <jfmezei.spamnot@vaxination.ca> - 2016-07-14 11:38 -0400
Re: Apollo 11 source code released Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-16 00:10 +0300
Re: Apollo 11 source code released Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-15 22:26 +0300
Re: Apollo 11 source code released Fred J. McCall <fjmccall@gmail.com> - 2016-07-20 10:49 -0700
Re: Apollo 11 source code released Snidely <snidely.too@gmail.com> - 2016-07-14 09:12 -0700
Re: Apollo 11 source code released JF Mezei <jfmezei.spamnot@vaxination.ca> - 2016-07-11 11:51 -0400
Re: Apollo 11 source code released Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-12 02:19 +0300
Re: Apollo 11 source code released Jeff Findley <jfindley@cinci.nospam.rr.com> - 2016-07-11 20:58 -0400
Re: Apollo 11 source code released Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-12 09:24 +0300
Re: Apollo 11 source code released Fred J. McCall <fjmccall@gmail.com> - 2016-07-12 10:10 -0700
Re: Apollo 11 source code released Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-13 21:07 +0300
Re: Apollo 11 source code released Fred J. McCall <fjmccall@gmail.com> - 2016-07-13 20:08 -0700
Re: Apollo 11 source code released JF Mezei <jfmezei.spamnot@vaxination.ca> - 2016-07-14 11:25 -0400
Re: Apollo 11 source code released Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-15 22:39 +0300
Re: Apollo 11 source code released Fred J. McCall <fjmccall@gmail.com> - 2016-07-20 10:40 -0700
Re: Apollo 11 source code released JF Mezei <jfmezei.spamnot@vaxination.ca> - 2016-07-12 14:41 -0400
Re: Apollo 11 source code released Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-12 23:26 +0300
Re: Apollo 11 source code released Jeff Findley <jfindley@cinci.nospam.rr.com> - 2016-07-12 21:41 -0400
Re: Apollo 11 source code released Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-13 08:54 +0300
Re: Apollo 11 source code released Jeff Findley <jfindley@cinci.nospam.rr.com> - 2016-07-13 06:43 -0400
Re: Apollo 11 source code released Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-13 21:08 +0300
Re: Apollo 11 source code released JF Mezei <jfmezei.spamnot@vaxination.ca> - 2016-07-14 11:34 -0400
Re: Apollo 11 source code released Niklas Holsti <niklas.holsti@tidorum.invalid> - 2016-07-15 23:06 +0300
Re: Apollo 11 source code released Jeff Findley <jfindley@cinci.nospam.rr.com> - 2016-07-15 19:48 -0400
Re: Apollo 11 source code released Jeff Findley <jfindley@cinci.nospam.rr.com> - 2016-07-15 19:59 -0400
Re: Apollo 11 source code released JF Mezei <jfmezei.spamnot@vaxination.ca> - 2016-07-17 12:00 -0400
Re: Apollo 11 source code released Jeff Findley <jfindley@cinci.nospam.rr.com> - 2016-07-17 12:14 -0400
Re: Apollo 11 source code released JF Mezei <jfmezei.spamnot@vaxination.ca> - 2016-07-17 12:56 -0400
Re: Apollo 11 source code released Fred J. McCall <fjmccall@gmail.com> - 2016-07-12 10:04 -0700
Re: Apollo 11 source code released Fred J. McCall <fjmccall@gmail.com> - 2016-07-12 09:43 -0700
Re: Apollo 11 source code released Alain Fournier <alain245@videotron.ca> - 2016-07-11 19:43 -0400
Re: Apollo 11 source code released Fred J. McCall <fjmccall@gmail.com> - 2016-07-10 11:39 -0700
Re: Apollo 11 source code released William Mook <mokmedical@gmail.com> - 2016-07-11 18:28 -0700
Page 2 of 3 — ← Prev page 1 [2] 3 Next page →
| From | Niklas Holsti <niklas.holsti@tidorum.invalid> |
|---|---|
| Date | 2016-07-16 00:10 +0300 |
| Message-ID | <dut1q6FhusqU1@mid.individual.net> |
| In reply to | #57027 |
On 16-07-14 18:38 , JF Mezei wrote:
>
>>> Fortran Common areas are global variables, not subroutine arguments that
>>> can point to different variables on each call.
>
>
> One register for the return address.
That is the Q register in the AGC.
> One register contains address of
> memory where a list of arguments is stored.
And which register is this, on the AGC? The AGC had a very small number
of registers, and no register that could be directly used as a pointer.
> So the subroutine looks at that register and goes out to pick
> arguments as needed.
With no register-indirect addressing modes, that is quite cumbersome.
Can be done, of course, with some effort and cost in time and space.
> Normally, an architecture has a calling standard that defines which
> register to use for that. (and which registers to put the return value
> before you return control to the calling code.
Today, yes, but today's computers have rather more registers, and more
addressing modes, than the AGC had. All AGC computations used the single
accumulator register (A) and a couple of auxiliary registers (Q, LP) for
division and multiplication. Any further argument-passing had to be done
through RAM. And of course there was no HW-supported stack, so
subroutines probably kept their local variables in statically allocated
RAM locations.
--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
[toc] | [prev] | [next] | [standalone]
| From | Niklas Holsti <niklas.holsti@tidorum.invalid> |
|---|---|
| Date | 2016-07-15 22:26 +0300 |
| Message-ID | <dusrnlFgghrU1@mid.individual.net> |
| In reply to | #57022 |
On 16-07-14 06:06 , Fred J. McCall wrote:
> Niklas Holsti <niklas.holsti@tidorum.invalid> wrote:
>
>> On 16-07-13 04:14 , Fred J. McCall wrote:
>>> Niklas Holsti <niklas.holsti@tidorum.invalid> wrote:
>>>
>>>> On 16-07-12 03:53 , Jeff Findley wrote:
>>>>> In article <duhkokFondfU1@mid.individual.net>,
>>>>> niklas.holsti@tidorum.invalid says...
>>>>>> But the Wikipedia entry also says this:
>>>>>>
>>>>>> "The AGC also had a sophisticated software interpreter, developed by the
>>>>>> MIT Instrumentation Laboratory, that implemented a virtual machine with
>>>>>> more complex and capable pseudo-instructions than the native AGC. These
>>>>>> instructions simplified the navigational programs. Interpreted code,
>>>>>> which featured double precision trigonometric, scalar and vector
>>>>>> arithmetic (16 and 24-bit), even an MXV (matrix × vector) instruction,
>>>>>> could be mixed with native AGC code. While the execution time of the
>>>>>> pseudo-instructions was increased (due to the need to interpret these
>>>>>> instructions at runtime) the interpreter provided many more instructions
>>>>>> than AGC natively supported and the memory requirements were much lower
>>>>>> than in the case of adding these instructions to the AGC native language
>>>>>> which would require additional memory built into the computer (at that
>>>>>> time the memory capacity was very expensive)...."
>>>>>
>>>>> The examples given for functionality of the interpreted code bits sound
>>>>> an awful lot like subroutines.
>>>>
>>>> Yes, but the basic AGC instruction set seems IMO very unfriendly to
>>>> subroutines -- it is possible to call ("TC", "Transfer Control") a
>>>> subroutine and save the return address, but it would be quite difficult
>>>> or at least cumbersome to pass arguments, as there are no easy
>>>> base+offset addressing modes.
>>>>
>>>> The INDEX instruction can be used to build such addressing modes, but
>>>> one base+index computation would take several instructions and at least
>>>> one temporary memory location if both "base" and "index" are dynamic
>>>> (non-constant) values, as would often be the case for accessing
>>>> subroutine arguments that are vectors or arrays.
>>>>
>>>
>>> Easy enough to use something like FORTRAN Common to fake this.
>>
>> Fortran Common areas are global variables, not subroutine arguments that
>> can point to different variables on each call.
>>
>
> Yes, I know. Here's how it would work. Suppose I have three
> parameters, A, B, and C, for a function, X. You build X to read the
> three values from some shared area (those 'global variables'). Right
> before a call to X, the caller sets the values of the three parameters
> in Common to the values desired. X reads those values and runs with
> them, changes them if that is desire behaviour, writes a functional
> return value to Common, whatever. When X returns, the caller go reads
> the values X set and moves on. Rinse and repeat. The only difference
> is that instead of the compiler managing everything on the stack frame
> for you and having rules about whether you're calling by reference or
> by value, you do all that manually around the call to X.
>
> This is dirt simple to do. I shouldn't have to explain it.
Of course I know that global variables can be used to pass data into and
out of subroutines, by copy-in and copy-out. I did not claim that
subroutines are impossible on the AGC.
The problem is that the AGC has no register-indirect addressing mode, so
pass-by-reference (pointers) is difficult, and the code to copy
parameter values in and result values out is long and slow.
If the calling sequence is as long as the subroutine being called, there
is no advantage to having a subroutine. This is independent of whether
you write that code manually or have a compiler doing it.
You can use a memory location as a pointer, by the INDEX instruction,
but this is very clumsy compared to the register-based indirect
addressing modes in later computers.
The AGC HW architecture is so spartan that I well understand why they
developed an interpretive virtual machine on top of it.
--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
[toc] | [prev] | [next] | [standalone]
| From | Fred J. McCall <fjmccall@gmail.com> |
|---|---|
| Date | 2016-07-20 10:49 -0700 |
| Message-ID | <q2evobdjs50366eke62s3qe7cfkq1ccurf@4ax.com> |
| In reply to | #57030 |
Niklas Holsti <niklas.holsti@tidorum.invalid> wrote:
>On 16-07-14 06:06 , Fred J. McCall wrote:
>> Niklas Holsti <niklas.holsti@tidorum.invalid> wrote:
>>
>>> On 16-07-13 04:14 , Fred J. McCall wrote:
>>>> Niklas Holsti <niklas.holsti@tidorum.invalid> wrote:
>>>>
>>>>> On 16-07-12 03:53 , Jeff Findley wrote:
>>>>>> In article <duhkokFondfU1@mid.individual.net>,
>>>>>> niklas.holsti@tidorum.invalid says...
>>>>>>> But the Wikipedia entry also says this:
>>>>>>>
>>>>>>> "The AGC also had a sophisticated software interpreter, developed by the
>>>>>>> MIT Instrumentation Laboratory, that implemented a virtual machine with
>>>>>>> more complex and capable pseudo-instructions than the native AGC. These
>>>>>>> instructions simplified the navigational programs. Interpreted code,
>>>>>>> which featured double precision trigonometric, scalar and vector
>>>>>>> arithmetic (16 and 24-bit), even an MXV (matrix × vector) instruction,
>>>>>>> could be mixed with native AGC code. While the execution time of the
>>>>>>> pseudo-instructions was increased (due to the need to interpret these
>>>>>>> instructions at runtime) the interpreter provided many more instructions
>>>>>>> than AGC natively supported and the memory requirements were much lower
>>>>>>> than in the case of adding these instructions to the AGC native language
>>>>>>> which would require additional memory built into the computer (at that
>>>>>>> time the memory capacity was very expensive)...."
>>>>>>
>>>>>> The examples given for functionality of the interpreted code bits sound
>>>>>> an awful lot like subroutines.
>>>>>
>>>>> Yes, but the basic AGC instruction set seems IMO very unfriendly to
>>>>> subroutines -- it is possible to call ("TC", "Transfer Control") a
>>>>> subroutine and save the return address, but it would be quite difficult
>>>>> or at least cumbersome to pass arguments, as there are no easy
>>>>> base+offset addressing modes.
>>>>>
>>>>> The INDEX instruction can be used to build such addressing modes, but
>>>>> one base+index computation would take several instructions and at least
>>>>> one temporary memory location if both "base" and "index" are dynamic
>>>>> (non-constant) values, as would often be the case for accessing
>>>>> subroutine arguments that are vectors or arrays.
>>>>>
>>>>
>>>> Easy enough to use something like FORTRAN Common to fake this.
>>>
>>> Fortran Common areas are global variables, not subroutine arguments that
>>> can point to different variables on each call.
>>>
>>
>> Yes, I know. Here's how it would work. Suppose I have three
>> parameters, A, B, and C, for a function, X. You build X to read the
>> three values from some shared area (those 'global variables'). Right
>> before a call to X, the caller sets the values of the three parameters
>> in Common to the values desired. X reads those values and runs with
>> them, changes them if that is desire behaviour, writes a functional
>> return value to Common, whatever. When X returns, the caller go reads
>> the values X set and moves on. Rinse and repeat. The only difference
>> is that instead of the compiler managing everything on the stack frame
>> for you and having rules about whether you're calling by reference or
>> by value, you do all that manually around the call to X.
>>
>> This is dirt simple to do. I shouldn't have to explain it.
>
>Of course I know that global variables can be used to pass data into and
>out of subroutines, by copy-in and copy-out. I did not claim that
>subroutines are impossible on the AGC.
>
No, you claimed "quite difficult". It's not.
>
>The problem is that the AGC has no register-indirect addressing mode, so
>pass-by-reference (pointers) is difficult, and the code to copy
>parameter values in and result values out is long and slow.
>
No. Anything the architecture could have helped you with can be done
manually in software, either implicitly or explicitly. Yes, there
will be minor speed impacts. MINOR speed impacts.
>
>If the calling sequence is as long as the subroutine being called, there
>is no advantage to having a subroutine. This is independent of whether
>you write that code manually or have a compiler doing it.
>
Wrong. There will always be a maintenance advantage.
--
"Some people get lost in thought because it's such unfamiliar
territory."
--G. Behn
[toc] | [prev] | [next] | [standalone]
| From | Snidely <snidely.too@gmail.com> |
|---|---|
| Date | 2016-07-14 09:12 -0700 |
| Message-ID | <mn.72287e07e0db7bae.127094@snitoo> |
| In reply to | #56987 |
Jeff Findley formulated the question : > In article <duhkokFondfU1@mid.individual.net>, > niklas.holsti@tidorum.invalid says... >> >> On 16-07-11 13:44 , Jeff Findley wrote: >>> In article <p2j6obt05vvmbg0i08afngatpmurap66e6@4ax.com>, >>> fjmccall@gmail.com says... >>>> >>>> JF Mezei <jfmezei.spamnot@vaxination.ca> wrote: >>>> >>>>> On 2016-07-10 13:33, Niklas Holsti wrote: >>>>> >>>>>> A custom-made computer: >>>>>> >>>>>> https://en.wikipedia.org/wiki/Apollo_Guidance_Computer >>>>> >>>>> >>>>> Very interesting read. Thanks. It mentions it was the first computer >>>>> made of integrated circuits. Looks like it was all fixed decimal >>>>> notation as opposed to floating point. That would have a big impact on >>>>> the heavy math done for guidance and navigation (lots of angles/trig >>>>> etc). >>>>> >>>>> Was all the code written in assembler or were portions done in higher >>>>> level languages ? >>>>> >>>> >>>> No HOL. Have you looked at the specifications for these things? >>> >>> The Wikipedia entry clearly says this, "AGC software was written in AGC >>> assembly language and stored on rope memory." >> >> But the Wikipedia entry also says this: >> >> "The AGC also had a sophisticated software interpreter, developed by the >> MIT Instrumentation Laboratory, that implemented a virtual machine with >> more complex and capable pseudo-instructions than the native AGC. These >> instructions simplified the navigational programs. Interpreted code, >> which featured double precision trigonometric, scalar and vector >> arithmetic (16 and 24-bit), even an MXV (matrix × vector) instruction, >> could be mixed with native AGC code. While the execution time of the >> pseudo-instructions was increased (due to the need to interpret these >> instructions at runtime) the interpreter provided many more instructions >> than AGC natively supported and the memory requirements were much lower >> than in the case of adding these instructions to the AGC native language >> which would require additional memory built into the computer (at that >> time the memory capacity was very expensive). The average >> pseudo-instruction required about 24 ms to execute. The assembler and >> version control system, named YUL for an early prototype Christmas >> Computer,[8] enforced proper transitions between native and interpreted >> code." >> >> Reminds me of the SWEET16 VM in the Apple II, >> https://en.wikipedia.org/wiki/SWEET16. > > The examples given for functionality of the interpreted code bits sound > an awful lot like subroutines. The description as quoted is insufficient to distinguish between a "subroutine-ish" stored program and a microcode implementation, but the former is more likely. Note that C64 and Apple II did their BASIC implementations this way (ROM subroutines), and Forth and Pascal were available as add-in boards. You could also think of the IBM-PC BIOS in this way, too. I understand the IBM 360 was an example of a computer using microcode where the microcode could be changed in the field. Microcode essentially provides a virtual machine written on top of a very dumb and very fast "inner processor". This is still used in x86 architectures, as well as having been part of PDP-11 and VAX building. The PDP-11 is rumored to have used the PDP-8 cpu/alu design to implement the "inner processor". (comment for the other branch of this thread: compiler designers did a lot of learning about optimization in the 1980s and 1990s) /dps -- There's nothing inherently wrong with Big Data. What matters, as it does for Arnold Lund in California or Richard Rothman in Baltimore, are the questions -- old and new, good and bad -- this newest tool lets us ask. (R. Lerhman, CSMonitor.com)
[toc] | [prev] | [next] | [standalone]
| From | JF Mezei <jfmezei.spamnot@vaxination.ca> |
|---|---|
| Date | 2016-07-11 11:51 -0400 |
| Message-ID | <5783c074$0$9185$c3e8da3$5d8fb80f@news.astraweb.com> |
| In reply to | #56978 |
On 2016-07-11 06:44, Jeff Findley wrote: > much on a C-64 using a "higher level language" due to the overhead of > incurred. Even in the 1980's, compilers, optimizers, and linkers > delivered code which was very "bloated". The 1960's would have been > far, far, worse. Not quite. older languages such as COBOL and Fortran provided reasonably efficient assembly. When IBM designed the 360 architecture, it had COBOL and FORTRAN in mind and provided instructiosn to make COBOL more efficient (fixed decimal math, as well as moving many characters in one operation). The simpler MOVE command in COBOL could result in a single MVC assembler instruction if it was a fixed length character field. However, the Apollo computer instruction set is very basic, so compilers would not have done a good job of making most efficient code generation. (not "bloated" but not "most efficient" either Also, because those computers had direct interfaces to devices/sensors, those interfaces become easier to managhe in assembler since you have direct access to memory, registers and interrupts. The WRITE and READ statements in Fortran would not be well suited for the type of equipment connected to the computers. Note: today, things are different because compilers are smart enough to organise code to make use of various capabilities for the architecture (pipelining, out of order execution, multiple execution units, pre-fetching, branch prediction etc). (However, stuff like object oriented langiuages have so many layers of bloat that optimization at the machine dode level still leaves it bloated). If I read correctly, the read-only "rope" memory that contained the programs had to manually be connected to represent the right bits. This makes it much easier to work with assembly language since the "compiled" code with the opcodes/operands in bits can more easily be matched to the original source code.
[toc] | [prev] | [next] | [standalone]
| From | Niklas Holsti <niklas.holsti@tidorum.invalid> |
|---|---|
| Date | 2016-07-12 02:19 +0300 |
| Message-ID | <duinshF2odsU1@mid.individual.net> |
| In reply to | #56981 |
On 16-07-11 18:51 , JF Mezei wrote:
> On 2016-07-11 06:44, Jeff Findley wrote:
>> much on a C-64 using a "higher level language" due to the overhead of
>> incurred. Even in the 1980's, compilers, optimizers, and linkers
>> delivered code which was very "bloated". The 1960's would have been
>> far, far, worse.
How might a 1980's or 1960's linker deliver "bloated code"? In those
days, linkers merely arranged given modules of code in memory and
corrected accordingly the cross-references from one module to another;
linkers did not generate or modify code in other ways.
> Not quite. older languages such as COBOL and Fortran provided reasonably
> efficient assembly.
>
> When IBM designed the 360 architecture, it had COBOL and FORTRAN in mind
> and provided instructiosn to make COBOL more efficient (fixed decimal
> math, as well as moving many characters in one operation). The simpler
> MOVE command in COBOL could result in a single MVC assembler instruction
> if it was a fixed length character field.
>
> However, the Apollo computer instruction set is very basic, so compilers
> would not have done a good job of making most efficient code generation.
> (not "bloated" but not "most efficient" either
Hmm. On the other hand, the compiler's search for the most efficient
translation can be easier for a target machine with a very small
instruction set, because the search-space is smaller. Today, using
search-based optimization, one could probably make a compiler that
generates very efficient code for the AGC, given also that an AGC
program cannot be very large.
But in the 1960s, the choice of assembly language (and the somewhat
enhanced virtual-machine interpreted language) was no doubt a
conservative and risk-reducing decision.
> Also, because those computers had direct interfaces to devices/sensors,
> those interfaces become easier to managhe in assembler since you have
> direct access to memory, registers and interrupts.
I don't think that is a major issue. All intermediate-level and
high-level languages used for embedded systems have standard or
implementation-specific means for easy, direct access to memory
locations and memory-mapped registers. In C, one just converts (casts)
the integer address of a memory location into a pointer, through which
the memory location can be read and written. In Ada one can do the same,
but one can also declare the memory location as a variable which has a
given address, and access the memory location through this variable,
without using pointer syntax.
> Note: today, things are different because compilers are smart enough to
> organise code to make use of various capabilities for the architecture
> (pipelining, out of order execution, multiple execution units,
> pre-fetching, branch prediction etc).
But the AGC had none of those architectural features, so this ability of
modern compilers cannot have played a role in the decision, then, to use
assembly language for the Apollo missions.
> If I read correctly, the read-only "rope" memory that contained the
> programs had to manually be connected to represent the right bits. This
> makes it much easier to work with assembly language since the "compiled"
> code with the opcodes/operands in bits can more easily be matched to the
> original source code.
I don't understand your reasoning here. Yes, the relationship between
assembly language source-code and bits in memory is more direct than for
higher-level languages, but for the AGC the rope-weaving was done by
dedicated staff, not by the programmers, so from the programmers' point
of view the only difference wrt the present-day method of automatically
transferring the assembler's output into a FLASH memory is that the
manual programming took longer and cost more.
Using assembly language may have made it easier to make local changes to
the program in such a way that only some of the "ropes" had to be
rewoven. Even today the maintenance of on-board spacecraft SW may
require that changes are made by local binary patches and not by
uploading a whole new software binary. If the SW is compiled into binary
from a high-level language, it may be difficult to control the compiler
so that a local change in the source language produces only a local
change in the binary, and not, say, a shifting of a large number of
binary instructions forwards or backwards in memory, which would require
a large patch.
--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
[toc] | [prev] | [next] | [standalone]
| From | Jeff Findley <jfindley@cinci.nospam.rr.com> |
|---|---|
| Date | 2016-07-11 20:58 -0400 |
| Message-ID | <MPG.31ee0ad63eaf7ca298979d@news.eternal-september.org> |
| In reply to | #56985 |
In article <duinshF2odsU1@mid.individual.net>, niklas.holsti@tidorum.invalid says... > > On 16-07-11 18:51 , JF Mezei wrote: > > On 2016-07-11 06:44, Jeff Findley wrote: > >> much on a C-64 using a "higher level language" due to the overhead of > >> incurred. Even in the 1980's, compilers, optimizers, and linkers > >> delivered code which was very "bloated". The 1960's would have been > >> far, far, worse. > > How might a 1980's or 1960's linker deliver "bloated code"? In those > days, linkers merely arranged given modules of code in memory and > corrected accordingly the cross-references from one module to another; > linkers did not generate or modify code in other ways. Could linkers of the time recognize duplicate functions (different name, but functionally identical) and discard the duplicate when linking? Yes, you can avoid this on a small project with careful software management, so I'll admit this would be a minor issue. Jeff -- All opinions posted by me on Usenet News are mine, and mine alone. These posts do not reflect the opinions of my family, friends, employer, or any organization that I am a member of.
[toc] | [prev] | [next] | [standalone]
| From | Niklas Holsti <niklas.holsti@tidorum.invalid> |
|---|---|
| Date | 2016-07-12 09:24 +0300 |
| Message-ID | <dujgojF7rs2U1@mid.individual.net> |
| In reply to | #56988 |
On 16-07-12 03:58 , Jeff Findley wrote:
> In article <duinshF2odsU1@mid.individual.net>,
> niklas.holsti@tidorum.invalid says...
>>
>> On 16-07-11 18:51 , JF Mezei wrote:
>>> On 2016-07-11 06:44, Jeff Findley wrote:
>>>> much on a C-64 using a "higher level language" due to the overhead of
>>>> incurred. Even in the 1980's, compilers, optimizers, and linkers
>>>> delivered code which was very "bloated". The 1960's would have been
>>>> far, far, worse.
>>
>> How might a 1980's or 1960's linker deliver "bloated code"? In those
>> days, linkers merely arranged given modules of code in memory and
>> corrected accordingly the cross-references from one module to another;
>> linkers did not generate or modify code in other ways.
>
> Could linkers of the time recognize duplicate functions (different name,
> but functionally identical) and discard the duplicate when linking?
Good point, I didn't even know that some linkers can do that today. This
optimisation seems to be motivated mainly by multiple auto-instantiation
of C++ templates, but it seems to me that intensive use of
assembly-language macros could have the same code-duplicating effect.
I'll have to check if the linker I'm using does that; I may want to
prevent it so that functions with identical machine code, but used for
different purposes, can be patched independently if necessary.
> Yes, you can avoid this on a small project with careful software
> management, so I'll admit this would be a minor issue.
On the other hand, one of the film documentaries referenced from the
Wikipedia entry says that when the Apollo AGC SW development got into
schedule problems and code-size problems, a trouble-shooter from NASA
found much duplicated code. That can easily happen in a rush project
with multiple programmers.
--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
[toc] | [prev] | [next] | [standalone]
| From | Fred J. McCall <fjmccall@gmail.com> |
|---|---|
| Date | 2016-07-12 10:10 -0700 |
| Message-ID | <jt8aobhkgumuoua3g2vg5acedu86qndf9l@4ax.com> |
| In reply to | #56990 |
Niklas Holsti <niklas.holsti@tidorum.invalid> wrote:
>On 16-07-12 03:58 , Jeff Findley wrote:
>> In article <duinshF2odsU1@mid.individual.net>,
>> niklas.holsti@tidorum.invalid says...
>>>
>>> On 16-07-11 18:51 , JF Mezei wrote:
>>>> On 2016-07-11 06:44, Jeff Findley wrote:
>>>>> much on a C-64 using a "higher level language" due to the overhead of
>>>>> incurred. Even in the 1980's, compilers, optimizers, and linkers
>>>>> delivered code which was very "bloated". The 1960's would have been
>>>>> far, far, worse.
>>>
>>> How might a 1980's or 1960's linker deliver "bloated code"? In those
>>> days, linkers merely arranged given modules of code in memory and
>>> corrected accordingly the cross-references from one module to another;
>>> linkers did not generate or modify code in other ways.
>>
>> Could linkers of the time recognize duplicate functions (different name,
>> but functionally identical) and discard the duplicate when linking?
>
>Good point, I didn't even know that some linkers can do that today. This
>optimisation seems to be motivated mainly by multiple auto-instantiation
>of C++ templates, but it seems to me that intensive use of
>assembly-language macros could have the same code-duplicating effect.
>
The part of the linker that takes care of pipelining will recognize
the two identical code sequences.
>
>I'll have to check if the linker I'm using does that; I may want to
>prevent it so that functions with identical machine code, but used for
>different purposes, can be patched independently if necessary.
>
Not an issue unless you're doing binary patches to runtime objects. If
you're doing that, you've got bigger problems than this. If you
relink on a 'patch', the linker will now recognize that the two
routines are different.
--
"The reasonable man adapts himself to the world; the unreasonable
man persists in trying to adapt the world to himself. Therefore,
all progress depends on the unreasonable man."
--George Bernard Shaw
[toc] | [prev] | [next] | [standalone]
| From | Niklas Holsti <niklas.holsti@tidorum.invalid> |
|---|---|
| Date | 2016-07-13 21:07 +0300 |
| Message-ID | <duneakF6tjlU1@mid.individual.net> |
| In reply to | #56997 |
On 16-07-12 20:10 , Fred J. McCall wrote:
> Niklas Holsti <niklas.holsti@tidorum.invalid> wrote:
>
>> On 16-07-12 03:58 , Jeff Findley wrote:
>>> In article <duinshF2odsU1@mid.individual.net>,
>>> niklas.holsti@tidorum.invalid says...
>>>>
>>>> On 16-07-11 18:51 , JF Mezei wrote:
>>>>> On 2016-07-11 06:44, Jeff Findley wrote:
>>>>>> much on a C-64 using a "higher level language" due to the overhead of
>>>>>> incurred. Even in the 1980's, compilers, optimizers, and linkers
>>>>>> delivered code which was very "bloated". The 1960's would have been
>>>>>> far, far, worse.
>>>>
>>>> How might a 1980's or 1960's linker deliver "bloated code"? In those
>>>> days, linkers merely arranged given modules of code in memory and
>>>> corrected accordingly the cross-references from one module to another;
>>>> linkers did not generate or modify code in other ways.
>>>
>>> Could linkers of the time recognize duplicate functions (different name,
>>> but functionally identical) and discard the duplicate when linking?
>>
>> Good point, I didn't even know that some linkers can do that today. This
>> optimisation seems to be motivated mainly by multiple auto-instantiation
>> of C++ templates, but it seems to me that intensive use of
>> assembly-language macros could have the same code-duplicating effect.
>>
>
> The part of the linker that takes care of pipelining will recognize
> the two identical code sequences.
>
>>
>> I'll have to check if the linker I'm using does that; I may want to
>> prevent it so that functions with identical machine code, but used for
>> different purposes, can be patched independently if necessary.
>>
>
> Not an issue unless you're doing binary patches to runtime objects.
That is exactly the reason for my concern. Because of limited uplink
bandwidth, on-board SW is still often repaired or modified by local
patches to the binary in EEPROM or RAM.
--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
[toc] | [prev] | [next] | [standalone]
| From | Fred J. McCall <fjmccall@gmail.com> |
|---|---|
| Date | 2016-07-13 20:08 -0700 |
| Message-ID | <ue0eob1v9uaqorclfbkc9lcl6gba2am5f6@4ax.com> |
| In reply to | #57020 |
Niklas Holsti <niklas.holsti@tidorum.invalid> wrote:
>On 16-07-12 20:10 , Fred J. McCall wrote:
>> Niklas Holsti <niklas.holsti@tidorum.invalid> wrote:
>>
>>> On 16-07-12 03:58 , Jeff Findley wrote:
>>>> In article <duinshF2odsU1@mid.individual.net>,
>>>> niklas.holsti@tidorum.invalid says...
>>>>>
>>>>> On 16-07-11 18:51 , JF Mezei wrote:
>>>>>> On 2016-07-11 06:44, Jeff Findley wrote:
>>>>>>> much on a C-64 using a "higher level language" due to the overhead of
>>>>>>> incurred. Even in the 1980's, compilers, optimizers, and linkers
>>>>>>> delivered code which was very "bloated". The 1960's would have been
>>>>>>> far, far, worse.
>>>>>
>>>>> How might a 1980's or 1960's linker deliver "bloated code"? In those
>>>>> days, linkers merely arranged given modules of code in memory and
>>>>> corrected accordingly the cross-references from one module to another;
>>>>> linkers did not generate or modify code in other ways.
>>>>
>>>> Could linkers of the time recognize duplicate functions (different name,
>>>> but functionally identical) and discard the duplicate when linking?
>>>
>>> Good point, I didn't even know that some linkers can do that today. This
>>> optimisation seems to be motivated mainly by multiple auto-instantiation
>>> of C++ templates, but it seems to me that intensive use of
>>> assembly-language macros could have the same code-duplicating effect.
>>>
>>
>> The part of the linker that takes care of pipelining will recognize
>> the two identical code sequences.
>>
>>>
>>> I'll have to check if the linker I'm using does that; I may want to
>>> prevent it so that functions with identical machine code, but used for
>>> different purposes, can be patched independently if necessary.
>>>
>>
>> Not an issue unless you're doing binary patches to runtime objects.
>>
>
>That is exactly the reason for my concern. Because of limited uplink
>bandwidth, on-board SW is still often repaired or modified by local
>patches to the binary in EEPROM or RAM.
>
So you already have so many horrible problems that you probably
haven't even thought about from doing this that you don't need to
worry about duplicate functions.
--
"The reasonable man adapts himself to the world; the unreasonable
man persists in trying to adapt the world to himself. Therefore,
all progress depends on the unreasonable man."
--George Bernard Shaw
[toc] | [prev] | [next] | [standalone]
| From | JF Mezei <jfmezei.spamnot@vaxination.ca> |
|---|---|
| Date | 2016-07-14 11:25 -0400 |
| Message-ID | <5787aef0$0$4514$c3e8da3$b280bf18@news.astraweb.com> |
| In reply to | #56997 |
On 2016-07-12 13:10, Fred J. McCall wrote: > The part of the linker that takes care of pipelining will recognize > the two identical code sequences. A linker does no such thing. It replaces external references with resolved addresses of such references, and builds an image file with the right header for that platform. It does no code optimization or elimination. It will detect multiple definitions of the same external name (for instance, if your link includes 2 compilation modules (.obj files) that have the same subroutine NAME defined. Not that today's environment usually hides the linker portion and makes things more confusing. Back then, the link was a separate application that was explicitelyt called with a list of modules to include and various option on how to resolve external references.
[toc] | [prev] | [next] | [standalone]
| From | Niklas Holsti <niklas.holsti@tidorum.invalid> |
|---|---|
| Date | 2016-07-15 22:39 +0300 |
| Message-ID | <dussfpFgmdoU1@mid.individual.net> |
| In reply to | #57025 |
On 16-07-14 18:25 , JF Mezei wrote:
> On 2016-07-12 13:10, Fred J. McCall wrote:
>
>> The part of the linker that takes care of pipelining will recognize
>> the two identical code sequences.
>
> A linker does no such thing. It replaces external references with
> resolved addresses of such references, and builds an image file with the
> right header for that platform. It does no code optimization or
> elimination.
Some current linkers do link-time optimization (LTO):
https://en.wikipedia.org/wiki/Interprocedural_optimization
https://en.wikipedia.org/wiki/GNU_Compiler_Collection#Optimization
LTO is sometimes a problem in benchmarks: if all the input data to the
benchmark are embedded in the source code, even hidden in a function of
its own, the compiler + linker can execute all or most of the benchmark
computation at compilation + linking time, as constant-folding
optimization, and no "benchmark code" is left for measuring the
performance...
Even before LTO, linkers for some architectures did "relaxation" which
optimized certain instructions such as jump instructions, choosing the
"shortest" or "nearest" form of jump instruction that can reach from the
jump instruction to the target address.
https://en.wikipedia.org/wiki/Linker_(computing)#Relaxation
--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
[toc] | [prev] | [next] | [standalone]
| From | Fred J. McCall <fjmccall@gmail.com> |
|---|---|
| Date | 2016-07-20 10:40 -0700 |
| Message-ID | <mpdvobt3d36k6ct8oss0qp29o8jj4f2nu6@4ax.com> |
| In reply to | #57025 |
JF Mezei <jfmezei.spamnot@vaxination.ca> wrote:
>On 2016-07-12 13:10, Fred J. McCall wrote:
>
>> The part of the linker that takes care of pipelining will recognize
>> the two identical code sequences.
>
>A linker does no such thing. It replaces external references with
>resolved addresses of such references, and builds an image file with the
>right header for that platform. It does no code optimization or
>elimination. It will detect multiple definitions of the same external
>name (for instance, if your link includes 2 compilation modules (.obj
>files) that have the same subroutine NAME defined.
>
You're ignorant. Educate yourself.
>
>Not that today's environment usually hides the linker portion and makes
>things more confusing. Back then, the link was a separate application
>that was explicitelyt called with a list of modules to include and
>various option on how to resolve external references.
>
And a bunch of options on how to optimize.
--
"Ignorance is preferable to error, and he is less remote from the
truth who believes nothing than he who believes what is wrong."
-- Thomas Jefferson
[toc] | [prev] | [next] | [standalone]
| From | JF Mezei <jfmezei.spamnot@vaxination.ca> |
|---|---|
| Date | 2016-07-12 14:41 -0400 |
| Message-ID | <578539e9$0$18125$c3e8da3$a9097924@news.astraweb.com> |
| In reply to | #56988 |
On 2016-07-11 20:58, Jeff Findley wrote: > Could linkers of the time recognize duplicate functions (different name, > but functionally identical) and discard the duplicate when linking? No. and I doubt that current linkers do. They will detect duplicate function definitions. And back then, there were no architecture specific optimizers such as GEM which is common now. (compiler generates "pseudo assembler", feeds it to GEM which is the one which geerates assembly code specific for and optimized for that architecture). Where early linkers did work no longer necessary is workout overlays. When you have limited memory, different subroutines/modules would be linked with the same memory addresses. But only one would be loaded at a time, and on sime systems this unloading of one module and loading of next was automatic (and slow). *(think of it as poor man's virtual memory). In various Apollo themed movies/TV series, you often hear about "loading program 64" and this is likely what happened.
[toc] | [prev] | [next] | [standalone]
| From | Niklas Holsti <niklas.holsti@tidorum.invalid> |
|---|---|
| Date | 2016-07-12 23:26 +0300 |
| Message-ID | <dul23oFju14U1@mid.individual.net> |
| In reply to | #57003 |
On 16-07-12 21:41 , JF Mezei wrote:
> On 2016-07-11 20:58, Jeff Findley wrote:
>
>> Could linkers of the time recognize duplicate functions (different name,
>> but functionally identical) and discard the duplicate when linking?
>
> No. and I doubt that current linkers do. They will detect duplicate
> function definitions.
Here is the reference I found after Jeff's post, from 2005:
http://blog.vladimirprus.com/2005/03/duplicate-function-bodies.html
Quote: "A couple of days ago I've learned that the Microsoft linker can
merge functions with binary identical bodies." Link:
https://blogs.msdn.microsoft.com/oldnewthing/20050322-00/?p=36113/
> Where early linkers did work no longer necessary is workout overlays.
That linker feature is still used in some small systems where the
architecture limits the address size but applications need more memory,
so the memory is "paged" or "mapped" or "banked" dynamically. Say, the
architectural address is 16 bits but there is 1 MiB of memory (RAM, not
disk) with a 20-bit physical address. The processor then provides 4
"extension" or "mapping" bits that can be set to view different parts of
the memory through the 16-bit, 64 KiB windows. Well, usually the low end
of the memory address is not mapped, so that some core code is visible
in all mappings.
Many current Intel-8051 microcontrollers (8-bit or 16-bit architectural
address) use this kind of memory "overlay". Atmel's 8-bit AVR
architecture also has such features, IIRC.
On the Modcomp IV minicomputer this was actually called "virtual memory"
and used as such: each program/process had a 16-bit "virtual" address
space but several programs/processes could be loaded at once into the
larger physical memory.
> When you have limited memory, different subroutines/modules would be
> linked with the same memory addresses. But only one would be loaded at a
> time, and on sime systems this unloading of one module and loading of
> next was automatic (and slow). *(think of it as poor man's virtual memory).
In the paged/mapped "overlay" systems, "loading" an overlay just means
changing the address-extension/mapping bits, so its very fast. (But some
linkers can/could be very slow at finding a workable overlay structure
automatically. I remember an HP brochure for the HP21MX computers, with
a 16-bit basic address but up to 2 MiB of memory. It quoted linking
times of some number of hours for large, but less than 2 MiB, overlaid
applications).
The Wikipedia entry on the AGC mentions three registers which seem to be
a kind of memory-address-extension register: Bank/Fbank, Ebank, and Sbank.
> In various Apollo themed movies/TV series, you often hear about "loading
> program 64" and this is likely what happened.
The AGC had no "mass memory" -- drum or disk -- only the core memory,
which was directly addressable, no "loading" needed. From where would a
program be loaded? This is just a guess, but to me it seems more likely
that "loading a program" meant starting the program and/or bringing it
into "focus" for commands, inputs, and outputs.
--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
[toc] | [prev] | [next] | [standalone]
| From | Jeff Findley <jfindley@cinci.nospam.rr.com> |
|---|---|
| Date | 2016-07-12 21:41 -0400 |
| Message-ID | <MPG.31ef666797473f1d98979e@news.eternal-september.org> |
| In reply to | #57003 |
In article <578539e9$0$18125$c3e8da3$a9097924@news.astraweb.com>, jfmezei.spamnot@vaxination.ca says... > > On 2016-07-11 20:58, Jeff Findley wrote: > > > Could linkers of the time recognize duplicate functions (different name, > > but functionally identical) and discard the duplicate when linking? > > No. and I doubt that current linkers do. They will detect duplicate > function definitions. Actually, I see this all the time in C++ when you define a pure virtual interface function in a base class (A) and then have the same implementation for two derived classes (B and C). For the names given in parenthesis, when debugging, the debugger will only show the implementation of that function for B even when called on an object of type C. Dead giveaway that the linker has discarded the duplicate implementation. Jeff -- All opinions posted by me on Usenet News are mine, and mine alone. These posts do not reflect the opinions of my family, friends, employer, or any organization that I am a member of.
[toc] | [prev] | [next] | [standalone]
| From | Niklas Holsti <niklas.holsti@tidorum.invalid> |
|---|---|
| Date | 2016-07-13 08:54 +0300 |
| Message-ID | <dum3bqFr0elU1@mid.individual.net> |
| In reply to | #57012 |
On 16-07-13 04:41 , Jeff Findley wrote:
> In article <578539e9$0$18125$c3e8da3$a9097924@news.astraweb.com>,
> jfmezei.spamnot@vaxination.ca says...
>>
>> On 2016-07-11 20:58, Jeff Findley wrote:
>>
>>> Could linkers of the time recognize duplicate functions (different name,
>>> but functionally identical) and discard the duplicate when linking?
>>
>> No. and I doubt that current linkers do. They will detect duplicate
>> function definitions.
>
> Actually, I see this all the time in C++ when you define a pure virtual
> interface function in a base class (A) and then have the same
> implementation for two derived classes (B and C). For the names given
> in parenthesis, when debugging, the debugger will only show the
> implementation of that function for B even when called on an object of
> type C. Dead giveaway that the linker has discarded the duplicate
> implementation.
I'm curious, which linker are you using?
--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
[toc] | [prev] | [next] | [standalone]
| From | Jeff Findley <jfindley@cinci.nospam.rr.com> |
|---|---|
| Date | 2016-07-13 06:43 -0400 |
| Message-ID | <MPG.31efe557ae776ae398979f@news.eternal-september.org> |
| In reply to | #57017 |
In article <dum3bqFr0elU1@mid.individual.net>, niklas.holsti@tidorum.invalid says... > > On 16-07-13 04:41 , Jeff Findley wrote: > > In article <578539e9$0$18125$c3e8da3$a9097924@news.astraweb.com>, > > jfmezei.spamnot@vaxination.ca says... > >> > >> On 2016-07-11 20:58, Jeff Findley wrote: > >> > >>> Could linkers of the time recognize duplicate functions (different name, > >>> but functionally identical) and discard the duplicate when linking? > >> > >> No. and I doubt that current linkers do. They will detect duplicate > >> function definitions. > > > > Actually, I see this all the time in C++ when you define a pure virtual > > interface function in a base class (A) and then have the same > > implementation for two derived classes (B and C). For the names given > > in parenthesis, when debugging, the debugger will only show the > > implementation of that function for B even when called on an object of > > type C. Dead giveaway that the linker has discarded the duplicate > > implementation. > > I'm curious, which linker are you using? Whatever is underneath the covers of Microsoft Dev Studio. Jeff -- All opinions posted by me on Usenet News are mine, and mine alone. These posts do not reflect the opinions of my family, friends, employer, or any organization that I am a member of.
[toc] | [prev] | [next] | [standalone]
| From | Niklas Holsti <niklas.holsti@tidorum.invalid> |
|---|---|
| Date | 2016-07-13 21:08 +0300 |
| Message-ID | <dunedoF6tjlU2@mid.individual.net> |
| In reply to | #57018 |
On 16-07-13 13:43 , Jeff Findley wrote:
> In article <dum3bqFr0elU1@mid.individual.net>,
> niklas.holsti@tidorum.invalid says...
>>
>> On 16-07-13 04:41 , Jeff Findley wrote:
>>> In article <578539e9$0$18125$c3e8da3$a9097924@news.astraweb.com>,
>>> jfmezei.spamnot@vaxination.ca says...
>>>>
>>>> On 2016-07-11 20:58, Jeff Findley wrote:
>>>>
>>>>> Could linkers of the time recognize duplicate functions (different name,
>>>>> but functionally identical) and discard the duplicate when linking?
>>>>
>>>> No. and I doubt that current linkers do. They will detect duplicate
>>>> function definitions.
>>>
>>> Actually, I see this all the time in C++ when you define a pure virtual
>>> interface function in a base class (A) and then have the same
>>> implementation for two derived classes (B and C). For the names given
>>> in parenthesis, when debugging, the debugger will only show the
>>> implementation of that function for B even when called on an object of
>>> type C. Dead giveaway that the linker has discarded the duplicate
>>> implementation.
>>
>> I'm curious, which linker are you using?
>
> Whatever is underneath the covers of Microsoft Dev Studio.
So probably the Microsoft linker. That agrees with the weblinks I found
earlier. Apparently the GNU linker is not doing it, which is a relief to me.
--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
[toc] | [prev] | [next] | [standalone]
Page 2 of 3 — ← Prev page 1 [2] 3 Next page →
Back to top | Article view | sci.space.policy
csiph-web