{"id":2086,"date":"2018-03-18T02:18:15","date_gmt":"2018-03-18T02:18:15","guid":{"rendered":"http:\/\/www.sydneysmith.com\/wordpress\/?p=2086"},"modified":"2018-03-18T02:18:15","modified_gmt":"2018-03-18T02:18:15","slug":"hp-55-emulator-bug","status":"publish","type":"post","link":"https:\/\/www.sydneysmith.com\/wordpress\/2086\/hp-55-emulator-bug\/","title":{"rendered":"HP-55 Emulator Bug"},"content":{"rendered":"<p>The HP-55 was before my time. I never had one, never considered one and never used one. However, it seems to be the immediate predecessor to the HP-25 and I wondered, &#8220;how did we get to this point?&#8221; so I looked.<\/p>\n<p>The problem though is: the very few HP-55 emulators that I found, don&#8217;t work. I know I&#8217;ve said similar things before, but it was true then too. Here&#8217;s the problem <!--more-->.<\/p>\n<p>I only found two emulators. One fairly recent one in javascript; and the &#8220;mother of all inventions&#8221; &#8211; nonpareil.<\/p>\n<h2>Javascript<\/h2>\n<p>The <a href=\"http:\/\/home.citycable.ch\/pierrefleur\/HP55\/default.htm\" rel=\"noopener\" target=\"_blank\">javascript one<\/a> did some strange things when you explored less commonly used (by scientific types at least) functions. The one sitting right there on the keyboard was &sum;+. Press that and the world ends.<\/p>\n<p>The microcode grinds to a complete halt and time, as it knows it, ceases to exist.<\/p>\n<p>The cause is easily found, once you know to look for it. If you check the javascript errors for the page you&#8217;ll see one for it trying to access n[mem][i] (arithmeticAndRegister.js line 261). The problem is mem is 40 and there are only 30 data registers (including program storage) in a HP-55.<\/p>\n<p>I&#8217;d like to thank Francois very much for doing his set of classic calculators. They are a really good starting point for understanding the older calculators. His collection also tends to be representative of our current state of knowledge of how the things worked. As a result, a bug in one of his is more likely to be due to the limits of what we know; rather than due to coding flaws.<\/p>\n<h2>Nonpareil<\/h2>\n<p>Eric&#8217;s <a href=\"http:\/\/nonpareil.brouhaha.com\/\" rel=\"noopener\" target=\"_blank\">nonpareil<\/a> is the starting point for anything HP calculator related. I&#8217;m pretty sure that was start of microcode emulators.<\/p>\n<p>I have a downloaded copy, probably version 0.79, and added the necessary GTK DLLs to run it on a Windows laptop.<\/p>\n<p>It runs quite nicely and it does include a HP-55 emulation.<\/p>\n<p>Pressing &sum;+ on that one gives &#8220;1.00&#8221; which is what you&#8217;d expect.<\/p>\n<p>So what&#8217;s different?<\/p>\n<p>Having a look through Eric&#8217;s source code (it&#8217;s open source) shows there were still many things left to figure out. One of my favorites is a comment &#8220;I don&#8217;t know what this instruction is supposed to do!&#8221;. It is an honest and factual report of the state of play at the time. That one isn&#8217;t in the bit we&#8217;re interested in though.<\/p>\n<p>The matching bit of code in nonpareil is protected by tests for invalid address values. There&#8217;s two bits, in proc_classic.c for op_c_to_data() and for op_data_to_c(), that either do nothing or set c to zero if the address value is out of range.<\/p>\n<p>Nonpareil works because it doesn&#8217;t do anything (in these cases).<\/p>\n<p>So does &sum;+ actually work? It does seem to. You can do 8 &sum;+ 9 &sum;+ and then get an average of 8.5.<\/p>\n<p>The fact that nonpareil works because it better guards against wrong values from the microcode; did get me really annoyed at whoever wrote the microcode for this calculator. Sending incorrect values to something for it to ignore, is really sloppy programming.<\/p>\n<p>BUT the story isn&#8217;t quite that simple.<\/p>\n<p>Whilst nonpareil APPEARS to work, if you look a little closer to tidy up loose ends, it doesn&#8217;t.<\/p>\n<p>Try doing 4 STO . 4 RCL . 4&#8243;. You&#8217;ll get &#8220;0.00&#8221; in nonpareil and &#8220;4.00&#8221; (I assume) on a real calculator. I can&#8217;t find a HP-55 manual online but <a href=\"http:\/\/www.thimet.de\/CalcCollection\/Calculators\/HP-55\/Contents.htm\" rel=\"noopener\" target=\"_blank\">www.thimet.de<\/a> created a quick reference that says statistical values are stored in registers &#8220;.0&#8221; through &#8220;.5&#8221;. If &#8220;STO . 4&#8221; isn&#8217;t working, why do the stats functions (&sum;+ etc) seem to work?<\/p>\n<p>The count of items (n) is stored in &#8220;.0&#8221;, the total (&sum;x) is stored in &#8220;.1&#8221;. Those storage registers appear to work (you can STO to and RCL from them). &#8220;.2&#8221; seems to work but, as you&#8217;ll soon understand, corrupts programs. &#8220;.3&#8221; and above either crash (javascript) or disappear entirely (nonpareil).<\/p>\n<p>If you put together an emulator for the HP-55 with logging so you can see where things go off the rails, you&#8217;ll see that a &#8220;STO n&#8221; looks like:<code><\/p>\n<pre>\r\n; (pressed STO then 5)\r\n01402 12 -> p                            ; P= 12\r\n01403 load 1                             ; C= 01500000000000 P= 11\r\n01404 c + 1 -> c[x]                      ; C= 01500000000001\r\n01405 c -> data address\r\n...\r\n01415 c <-> m                            ; C= 08500000000000 M= 00110020000905\r\n*** c -> ram[15]\r\n01416 c -> data<\/pre>\n<p><\/code>so &#8220;STO 5&#8221; uses ram[15]<\/p>\n<p>A &#8220;STO . n&#8221; looks like:<code><\/p>\n<pre>\r\n; (pressed STO . 4)\r\n01402 12 -> p                            ; P= 12\r\n01403 load 1                             ; C= 01400000000000 P= 11\r\n01404 c + 1 -> c[x]                      ; C= 01400000000001\r\n01405 c -> data address\r\n...\r\n01515 a <-> c[w]                         ; A= 00110020000904 C= 04000000000000\r\n01516 c -> data address\r\n...\r\n01415 c <-> m                            ; C= 05000000000000 M= 00110020000904\r\n*** c -> ram[40]\r\n01416 c -> data<\/pre>\n<p><\/code>so &#8220;STO . 4&#8221; sets up to use ram[14], realizes &#8220;.&#8221; was pressed, and changes to use ram[40] instead.<\/p>\n<p>Now whilst changing one&#8217;s mind is messy, in the interests of fitting all this into limited ROM space, it might have worked out better to do it this way. The more important point though is: clearly, ram[40] is not what&#8217;s intended in a system with only 30 registers. ram[4] is a more likely intent for &#8220;STO . 4&#8221;.<\/p>\n<p>It is no wonder nonpareil was having to guard against wrong address values.<\/p>\n<p>It is also no wonder that &#8220;STO . 4&#8221; (and above, and &#8220;STO . 3&#8221;) were not storing anything.<\/p>\n<p>The emulators really should store something when they are seeing values of 30, 40, 50, etc.<\/p>\n<p>The interesting thing is the emulator code for &#8220;c -&gt; data address&#8221; contains a comment saying &#8220;2 digits for HP-55&#8221;. That suggests it might have been 1 digit before then. One digit makes sense given what we&#8217;re seeing. That would give us &#8220;3&#8221;, &#8220;4&#8221;, &#8220;5&#8221; etc instead of &#8220;30&#8221;, &#8220;40&#8221;, &#8220;50&#8221; etc. One digit values work. Two digit ones don&#8217;t in the cases we&#8217;re looking at.<\/p>\n<p>It can&#8217;t be something simple like a trailing &#8220;0&#8221; in digit position 2, or we&#8217;d never be able to access ram[10] or ram[20]. There has to be something else providing the clue or acting as a flag.<\/p>\n<p>The obvious one in the code above, now we know to look, is c[0].<\/p>\n<p>Every time we want a two-digit address, c[0] is 1. Every time we want\/need\/have to use a one digit address, c[0] is 0. See 01404 and 01515. I have done a number of additional tests and even added a &#8220;print statement&#8221; into the &#8220;c -&gt; data address&#8221; statement to check what happens when I enter a program step. The c[0] value is always &#8220;1&#8221; for the newer, two-digit mode, and always &#8220;0&#8221; for single digit mode.<\/p>\n<h2>The Solution<\/h2>\n<p>Given what we&#8217;re seeing, this means we can change the javascript from:<br \/>\n<code><\/p>\n<pre>\r\nfunction cdataaddr() {\r\n\tmem = 10*c[12] + c[11]; \/\/ 2-digit for HP-55 addressing\r\n}<\/pre>\n<p><\/code><\/p>\n<p>To:<br \/>\n<code><\/p>\n<pre>\r\nfunction cdataaddr() {\r\n\tif (c[0]==0) mem= c[12];               \/\/ 1-digit for HP-55 and others\r\n\tif (c[0]==1) mem= 10*c[12] + c[11];    \/\/ 2-digit for HP-55 addressing\r\n}<\/pre>\n<p><\/code><\/p>\n<p>Perhaps it should be c[0]!=0 for two digit. Perhaps the door was left open for 1000 memories with c[0]==2 being three digit addresses. We&#8217;d need to write a ROM and feed instructions to the real thing and see what it does to know for sure. For now at least, the above fix (and equivalent for nonpareil and any C-based derivatives) seems to work well for the HP-55.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The HP-55 was before my time. I never had one, never considered one and never used one. However, it seems to be the immediate predecessor to the HP-25 and I wondered, &#8220;how did we get to this point?&#8221; so I looked. The problem though is: the very few HP-55 emulators that I found, don&#8217;t work. &hellip; <a href=\"https:\/\/www.sydneysmith.com\/wordpress\/2086\/hp-55-emulator-bug\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">HP-55 Emulator Bug<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[16,5,71],"tags":[40,32],"_links":{"self":[{"href":"https:\/\/www.sydneysmith.com\/wordpress\/wp-json\/wp\/v2\/posts\/2086"}],"collection":[{"href":"https:\/\/www.sydneysmith.com\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sydneysmith.com\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sydneysmith.com\/wordpress\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sydneysmith.com\/wordpress\/wp-json\/wp\/v2\/comments?post=2086"}],"version-history":[{"count":5,"href":"https:\/\/www.sydneysmith.com\/wordpress\/wp-json\/wp\/v2\/posts\/2086\/revisions"}],"predecessor-version":[{"id":2091,"href":"https:\/\/www.sydneysmith.com\/wordpress\/wp-json\/wp\/v2\/posts\/2086\/revisions\/2091"}],"wp:attachment":[{"href":"https:\/\/www.sydneysmith.com\/wordpress\/wp-json\/wp\/v2\/media?parent=2086"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sydneysmith.com\/wordpress\/wp-json\/wp\/v2\/categories?post=2086"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sydneysmith.com\/wordpress\/wp-json\/wp\/v2\/tags?post=2086"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}