EDSAC (only for the harshest)

What comes to your mind when you hear “low-level programming”? Maybe C ++? Continuous pointer control, attempts to optimize performance, memory consumption? Or are you probably representing assembly instructions of some popular architecture today?



If you remember how a puncher pierced a punched tape, one hole after another, for many hours, then this article is for you! Welcome under the cut! :)



Lasciate ogni speranza, voi ch'entrate

- Dante Alighieri, La Divina Commedia


EDSAC - "Electronic Delay Storage Automatic Calculator", was created in Cambridge in 1949 for military purposes. Now in oblivion, they remember him only for educational purposes in the N-th province in the little-known Alma Mater, the daughter of the Petersburg State University.

There is also The EDSAC Replica Project , where a powerful bunch of enthusiasts are creating an emulator and EDSAC guides to preserve the memory of this amazing device.



One of the nicer features of the EDSAC is that it is conceptually a very simple machine.

- Tutorial Guide to the EDSAC Simulator


The dryndulet looks like this:



Fig 1.1. - EDSAC Simulator up close.





Fig 1.2. - EDSAC Simulator away.



You can download it here .



On the left you can see a text editor for instructions. There are two types of instructions: Initial Orders 1 (hereinafter IO1) and Initial Orders 2 (mega advanced). The editor highlights the changed line in yellow, green - the saved ones. Comments are enclosed in []. The editor has memory several steps back, so you can roll back the program by pressing Ctrl + Z. All this used to be typed on punched tape, this is a remake. The first instruction in IO1 is TNS, where N is the address of the last line with instruction + 1. The simplest EDSAC program is:



Listing 1. - EDSAC order code, the simplest program.
T32S







She doesn't do anything. Like most of my programs. The countdown starts from 31, because cells from 0..30 are initially used to start the machine itself, later they can be used as memory cells.



By the way, by default the simulator is set to IO2, to switch it to IO1, click on the top panel of EDSAC -> IO1. It is started by the Start button, stopped by Stop, Single EP - step-by-step debugging, for this you need to write Z0S / ZS / Z0F / ZF first.



On the right you can see the simulator and the contents of the computer memory. The words are 17-bit, a total of 1024 memory cells (or 35-bit, 512 memory cells, as it will be more convenient, in the middle there is a mysterious "sandwich-digit"). There is also an accumulator (RAM), 71-bit, and a 35-bit multiplication register. The simulator supports disk telephone input, printing. By turning on hints , you can look at the contents of memory cells by hovering over them with the mouse. A number in 10CC will appear at the top. You can also view the contents of the accumulator and the multiplication register.





Fig 2. - Format of a machine word.





Fig 3. - Format of machine instructions.



About numbers. The number is written into memory in two's complement using the instruction: PNS or PNL, where N is a factor before two. For example, P0S = 2 * 0 + 0 = 0, P0L = 2 * 0 + 1 = 1, P1S = 2, P1L = 3, etc. Negative numbers are written in complement code, you can read about this in the tutorial . EDSAC also works with fractional numbers. Short word symbol S (F for IO2) and L (D). Not only the numbers, but also the instructions change their meaning depending on this.



There are a couple of guides, the main one and the abbreviated one , I recommend the last one because there are fewer beeches, the material is presented more clearly, working examples.



To make the code given in them work, you need to replace the first line of ZOS / ZS / Z0F / ZF with X0S / X0F. See instructions there, or already in the comments to the code.



Over the course of several months, many versions of the decimal printing procedure have been produced. If the programmer was impenetrably stupid, or was a complete idiot and a complete loser, then the conversion routine would take about a hundred instructions from him. But any hacker worth his name could fit it into less space. Ultimately, by alternately removing instructions from one place to another, the procedure was reduced to about fifty instructions.



- Stephen Levy, Hackers: Heroes of the Computer Revolution


So, my task was to write a program to print the n-th line of Pascal's triangle.



Listing 2. - Kotlin, outputting the 3rd line of Pascal's triangle.
fun main(args: Array<String>) {
    var a = 1
    var row = 3
    row += 1
    for (i in 1..row) {
        print(a)
        print(" ")
        a = a * (row - i) / i
    }
}

      
      







There will be a nested loop here, since division must be done manually.



Listing 3. - EDSAC order code, integer division, round down.
[31] T56S

[32] E37S [ ]

[33] P3L [ = 5]

[34] P1L [ = 2]

[35] P0S [ , 0]

[36] P0L [1]

[37] A35S [ ]

[38] T2S [ 2 ]

[39] A33S [ ]

[40] T1S [ 1 ]

[41] A1S [ ]

[42] S34S [ ]

[43] T1S [ 1]

[44] A2S [ ]

[45] A36S [ 1]

[46] T2S [ 1 ]

[47] A1S [ ]

[48] G50S [ < 0, ]

[49] T1S [ ]

[50] E41S[ ]

[51] T0S [ ]

[52] A2S [ ]

[53] S36S [ 1]

[54] T2S [ ]

[55] Z0S [ ]









As you may have noticed, the addressing is absolute, which causes a headache, aggression, causes gritting teeth, hatred, disappointment, anger, difficulties (this was fixed in version 2 of Initial Orders). When one line is shifted, a LOT is shifted at once . And it is necessary to rewrite the addresses of all "floated" lines.



Finally the solution:



Listing 4. - EDSAC order code, IO1, nth line of Pascal's triangle.
[31] T154S [ +1]

[32] E84S [ 84 , ]

[33] PS [ ]

[34] PS [ ]

[35] P10000S [ , 10, 10^4]

[36] P1000S [ , 10, 10^3]

[37] P100S [ , 10, 10^2]

[38] P10S [ , 10, 10^1]

[39] P1S [ , 10, 10^0]

[40] QS [ ]

[41] #S [ ]

[42] A40S [ ]

[43] !S [ ]

[44] &S [ ]

[45] @S [ ]

[46] O43S [ ]

[47] O33S [ 10]

[48] PS [ ]

[49] A46S [ 46 ]

[50] T65S [ 65, ]

[51] T300S [ ]

[52] A35S [ 35, 10000<<1]

[53] T34S [ 34, ]

[54] E61S [ >= 0, 61]

[55] T48S [ 48, ]

[56] A47S [ 47 ]

[57] T65S [ 65, ]

[58] A33S [ 33 ]

[59] A40S [ 40 ]

[60] T33S [ 33, ]

[61] A48S [ 48 ]

[62] S34S [ ]

[63] E55S [ >= 0, , 55]

[64] A34S [ 34 ]

[65] PS [ , ]

[66] T48S [ 48, ]

[67] T33S [ 33,

]

[68] A52S [ 52 ]

[69] A4S [ 1]

[70] U52S [ 52]

[71] S42S [ ]

[72] G51S [ < 0, 51 ]

[73] A103S [ 103 ]

[74] T52S [ 52, ]

[75] PS [ ]

[76] PS [ ]

[77] PS [const = 0]

[78] PS [const = 0]

[79] PS [const = 0]

[80] E100S [ 100]

[81] E104S [ 104]

[82] P5S [ , P S,

10]

[83] E123S [ , 123]

[84] A110S [ 2]

[85] T30S [ 30, ]

[86] O41S [ ]

[87] T300S [ ]

[88] O44S [ ]

[89] O44S [ ]

[90] A76S [ ]

[91] A4S [ 1]

[92] T76S [ , ]

[93] E113S [ 113]

[94] T300S [ ]

[95] A30S [ 30 , ]

[96] T48S [ 48, ]

[97] A80S [ 80]

[98] T75S [ 75 , ]

[99] E49S [ ]

[100] A81S [ 81]

[101] T75S [ 75, ]

[102] E49S [ ]

[103] A35S [ ]

[104] A76S [ 76]

[105] S82S [ ]

[106] S110S [ 2]

[107] G87S [ <0, 87]

[108] X0S [ ]

[109] ZS [ , ]

[110] P1S [const = 2]

[111] P2S [const = 4]

[112] P0L [const = 1]

[113] T300S [ ]

[114] A76S [ 76 ]

[115] S111S [ 111 , 4]

[116] E124S [ >=0, 124 ]

[117] T300S [ ]

[118] A30S [ 30 ]

[119] T48S [ 48, , ]

[120] A83S [ 83]

[121] T75S [ 75 ]

[122] E49S [ ]

[123] O44S [ ]

[124] O44S [ ]

[125] T300S [ ]

[126] A82S [ ]

[127] A110S [ 2]

[128] S76S [ ]

[129] T29S [ 29, ]

[130] H29S [ 29 ]

[131] V30S [ 30 , ]

[132] L64S [ 8 ]

[133] L32S [ 7 ]

[134] T30S [ 30 ]

[135] T2S [ 2, ]

[136] A30S [ 30]

[137] T1S [ 1 , ]

[138] A1S [ 1, ]

[139] S76S [ 76]

[140] T1S [ 1, ]

[141] A2S [ 2]

[142] A110S [ 1 110]

[143] T2S [ 1 2, ]

[144] A1S [ 1]

[145] G147S [ < 0, , 147]

[146] T1S [ 1, ]

[147] E138S[ >= 0, , 138 , ]

[148] T300S [ ]

[149] A2S [ 2]

[150] S110S [ 1 110]

[151] U2S [ 2]

[152] T30S [ 30, ]

[153] E94S [ 94, ]









What can I say about IO2? Supports subroutines, relative addressing, command set extended.



The same program on IO2:



Listing 5. - EDSAC order code, IO2, nth row of Pascal's triangle.
..PK

T56K

[P6, ]

GKA3FT25@H29@VFT4DA3@TFH30@S6@T1F

V4DU4DAFG26@TFTFO5FA4DF4FS4F

L4FT4DA1FS3@G9@EFSFO31@E20@J995FJF!F

..PZ

[ n- ]

GK [ ]

[0] XF [ , ]

[1] O34@ [ , 34]

[2] O35@ [ , 35]

[3] O36@ [ , 36]

[4] TF [ ]

[5] A27@ [ 27 ]

[6] TF [ 0 , ]

[7] A7@ [ ]

[8] G56F [ P6]

[9] T20@ [ 20 ]

[10] A28@ [ ]

[11] A31@ [ 1]

[12] U28@ [ 28]

[13] T20@ [ 20, ]

[14] A33@ [ ]

[15] A31@ [+1]

[16] S28@ [ 28]

[17] T20@ [ 20, ]

[18] E37@ [ , 37]

[19] PD [const = 1]

[20] XF [ ]

[21] XF [ ]

[22] A33@ [ 33 ]

[23] A31@ [+1]

[24] S28@ [ 28 , ]

[25] E2@ [ >= 0, , 2]

[26] ZF [ , ]

[27] PD [ ]

[28] PF [ ]

[29] PD [ ]

[30] PD [ ]

[31] PD [const = 1]

[32] P1F [ ]

[33] P2D [ , EDSAC]

[34] #F [ ]

[35] @F [ ]

[36] &F [ ]

[37] H20@ [ 20 ]

[38] V27@ [ 27 , ]

[39] L1024F [ 12 ]

[40] L4F [ 4 ]

[41] T20@ [ 20 , ]

[42] T102@ [ 102, ]

[43] A20@ [ 20]

[44] T101@ [ 101 , ]

[45] A101@ [ 101, ]

[46] S28@ [ 28]

[47] T101@ [ 101, ]

[48] A102@ [ 102]

[49] A31@ [ 1 31]

[50] T102@ [ 1 102, ]

[51] A101@ [ 101]

[52] G54@ [ < 0, , 54]

[53] T101@ [ 101, ]

[54] E45@ [ >= 0, , 45 , ]

[55] T200@ [ ]

[56] A102@ [ ]

[57] S31@ [ 1 102]

[58] U102@ [ 102]

[59] T27@ [ 27, ]

[60] E22@ [ 22, ]

[61] EZPF [ ]











Fig 4. - Conclusion for indicator = 5.



I hope you enjoyed this article and you are imbued with the origins of programming. When you write such code, you begin to appreciate all those levels of abstraction that appeared later, you understand what a long way the programming language went to become what they are. Thank you for your time!



PS Dear friends from the province of N, no thanks for the code kindly provided by me, if you have the same version as me. Good luck with RISC-V!



PPS Excellent code examples for the EDSAC IO2 are provided here .



PPPS Code is published under the MIT license.
Copyright 2021, ALEKSEI VASILEV

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the «Software»), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED «AS IS», WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.




All Articles