CINXE.COM
Ken Shirriff's blog: March 2023
<!DOCTYPE html> <html class='v2' dir='ltr' xmlns='http://www.w3.org/1999/xhtml' xmlns:b='http://www.google.com/2005/gml/b' xmlns:data='http://www.google.com/2005/gml/data' xmlns:expr='http://www.google.com/2005/gml/expr'> <head> <link href='https://www.blogger.com/static/v1/widgets/3566091532-css_bundle_v2.css' rel='stylesheet' type='text/css'/> <meta content='width=1100' name='viewport'/> <meta content='text/html; charset=UTF-8' http-equiv='Content-Type'/> <meta content='blogger' name='generator'/> <link href='http://www.righto.com/favicon.ico' rel='icon' type='image/x-icon'/> <link href='http://www.righto.com/2023/03/' rel='canonical'/> <link rel="alternate" type="application/atom+xml" title="Ken Shirriff's blog - Atom" href="http://www.righto.com/feeds/posts/default" /> <link rel="alternate" type="application/rss+xml" title="Ken Shirriff's blog - RSS" href="http://www.righto.com/feeds/posts/default?alt=rss" /> <link rel="service.post" type="application/atom+xml" title="Ken Shirriff's blog - Atom" href="https://www.blogger.com/feeds/6264947694886887540/posts/default" /> <!--Can't find substitution for tag [blog.ieCssRetrofitLinks]--> <meta content='http://www.righto.com/2023/03/' property='og:url'/> <meta content='Ken Shirriff's blog' property='og:title'/> <meta content='Computer history, restoring vintage computers, IC reverse engineering, and whatever' property='og:description'/> <title>Ken Shirriff's blog: March 2023</title> <style type='text/css'>@font-face{font-family:'Play';font-style:normal;font-weight:400;font-display:swap;src:url(//fonts.gstatic.com/s/play/v19/6aez4K2oVqwIvtg2H70Q13HqPA.woff2)format('woff2');unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F;}@font-face{font-family:'Play';font-style:normal;font-weight:400;font-display:swap;src:url(//fonts.gstatic.com/s/play/v19/6aez4K2oVqwIvtE2H70Q13HqPA.woff2)format('woff2');unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;}@font-face{font-family:'Play';font-style:normal;font-weight:400;font-display:swap;src:url(//fonts.gstatic.com/s/play/v19/6aez4K2oVqwIvtY2H70Q13HqPA.woff2)format('woff2');unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF;}@font-face{font-family:'Play';font-style:normal;font-weight:400;font-display:swap;src:url(//fonts.gstatic.com/s/play/v19/6aez4K2oVqwIvto2H70Q13HqPA.woff2)format('woff2');unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB;}@font-face{font-family:'Play';font-style:normal;font-weight:400;font-display:swap;src:url(//fonts.gstatic.com/s/play/v19/6aez4K2oVqwIvts2H70Q13HqPA.woff2)format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}@font-face{font-family:'Play';font-style:normal;font-weight:400;font-display:swap;src:url(//fonts.gstatic.com/s/play/v19/6aez4K2oVqwIvtU2H70Q13E.woff2)format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}</style> <style id='page-skin-1' type='text/css'><!-- /* ----------------------------------------------- Blogger Template Style Name: Simple Designer: Blogger URL: www.blogger.com ----------------------------------------------- */ /* Variable definitions ==================== <Variable name="keycolor" description="Main Color" type="color" default="#66bbdd"/> <Group description="Page Text" selector="body"> <Variable name="body.font" description="Font" type="font" default="normal normal 12px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> <Variable name="body.text.color" description="Text Color" type="color" default="#222222"/> </Group> <Group description="Backgrounds" selector=".body-fauxcolumns-outer"> <Variable name="body.background.color" description="Outer Background" type="color" default="#66bbdd"/> <Variable name="content.background.color" description="Main Background" type="color" default="#ffffff"/> <Variable name="header.background.color" description="Header Background" type="color" default="transparent"/> </Group> <Group description="Links" selector=".main-outer"> <Variable name="link.color" description="Link Color" type="color" default="#2288bb"/> <Variable name="link.visited.color" description="Visited Color" type="color" default="#888888"/> <Variable name="link.hover.color" description="Hover Color" type="color" default="#33aaff"/> </Group> <Group description="Blog Title" selector=".header h1"> <Variable name="header.font" description="Font" type="font" default="normal normal 60px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> <Variable name="header.text.color" description="Title Color" type="color" default="#3399bb" /> </Group> <Group description="Blog Description" selector=".header .description"> <Variable name="description.text.color" description="Description Color" type="color" default="#777777" /> </Group> <Group description="Tabs Text" selector=".tabs-inner .widget li a"> <Variable name="tabs.font" description="Font" type="font" default="normal normal 14px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> <Variable name="tabs.text.color" description="Text Color" type="color" default="#999999"/> <Variable name="tabs.selected.text.color" description="Selected Color" type="color" default="#000000"/> </Group> <Group description="Tabs Background" selector=".tabs-outer .PageList"> <Variable name="tabs.background.color" description="Background Color" type="color" default="#f5f5f5"/> <Variable name="tabs.selected.background.color" description="Selected Color" type="color" default="#eeeeee"/> </Group> <Group description="Post Title" selector="h3.post-title, .comments h4"> <Variable name="post.title.font" description="Font" type="font" default="normal normal 22px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> </Group> <Group description="Date Header" selector=".date-header"> <Variable name="date.header.color" description="Text Color" type="color" default="#222222"/> <Variable name="date.header.background.color" description="Background Color" type="color" default="transparent"/> <Variable name="date.header.font" description="Text Font" type="font" default="normal bold 11px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> <Variable name="date.header.padding" description="Date Header Padding" type="string" default="inherit"/> <Variable name="date.header.letterspacing" description="Date Header Letter Spacing" type="string" default="inherit"/> <Variable name="date.header.margin" description="Date Header Margin" type="string" default="inherit"/> </Group> <Group description="Post Footer" selector=".post-footer"> <Variable name="post.footer.text.color" description="Text Color" type="color" default="#666666"/> <Variable name="post.footer.background.color" description="Background Color" type="color" default="#f9f9f9"/> <Variable name="post.footer.border.color" description="Shadow Color" type="color" default="#eeeeee"/> </Group> <Group description="Gadgets" selector="h2"> <Variable name="widget.title.font" description="Title Font" type="font" default="normal bold 11px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> <Variable name="widget.title.text.color" description="Title Color" type="color" default="#000000"/> <Variable name="widget.alternate.text.color" description="Alternate Color" type="color" default="#999999"/> </Group> <Group description="Images" selector=".main-inner"> <Variable name="image.background.color" description="Background Color" type="color" default="#ffffff"/> <Variable name="image.border.color" description="Border Color" type="color" default="#eeeeee"/> <Variable name="image.text.color" description="Caption Text Color" type="color" default="#222222"/> </Group> <Group description="Accents" selector=".content-inner"> <Variable name="body.rule.color" description="Separator Line Color" type="color" default="#eeeeee"/> <Variable name="tabs.border.color" description="Tabs Border Color" type="color" default="#eeeeee"/> </Group> <Variable name="body.background" description="Body Background" type="background" color="#f6fbf6" default="$(color) none repeat scroll top left"/> <Variable name="body.background.override" description="Body Background Override" type="string" default=""/> <Variable name="body.background.gradient.cap" description="Body Gradient Cap" type="url" default="url(https://resources.blogblog.com/blogblog/data/1kt/simple/gradients_light.png)"/> <Variable name="body.background.gradient.tile" description="Body Gradient Tile" type="url" default="url(https://resources.blogblog.com/blogblog/data/1kt/simple/body_gradient_tile_light.png)"/> <Variable name="content.background.color.selector" description="Content Background Color Selector" type="string" default=".content-inner"/> <Variable name="content.padding" description="Content Padding" type="length" default="10px" min="0" max="100px"/> <Variable name="content.padding.horizontal" description="Content Horizontal Padding" type="length" default="10px" min="0" max="100px"/> <Variable name="content.shadow.spread" description="Content Shadow Spread" type="length" default="40px" min="0" max="100px"/> <Variable name="content.shadow.spread.webkit" description="Content Shadow Spread (WebKit)" type="length" default="5px" min="0" max="100px"/> <Variable name="content.shadow.spread.ie" description="Content Shadow Spread (IE)" type="length" default="10px" min="0" max="100px"/> <Variable name="main.border.width" description="Main Border Width" type="length" default="0" min="0" max="10px"/> <Variable name="header.background.gradient" description="Header Gradient" type="url" default="none"/> <Variable name="header.shadow.offset.left" description="Header Shadow Offset Left" type="length" default="-1px" min="-50px" max="50px"/> <Variable name="header.shadow.offset.top" description="Header Shadow Offset Top" type="length" default="-1px" min="-50px" max="50px"/> <Variable name="header.shadow.spread" description="Header Shadow Spread" type="length" default="1px" min="0" max="100px"/> <Variable name="header.padding" description="Header Padding" type="length" default="30px" min="0" max="100px"/> <Variable name="header.border.size" description="Header Border Size" type="length" default="1px" min="0" max="10px"/> <Variable name="header.bottom.border.size" description="Header Bottom Border Size" type="length" default="0" min="0" max="10px"/> <Variable name="header.border.horizontalsize" description="Header Horizontal Border Size" type="length" default="0" min="0" max="10px"/> <Variable name="description.text.size" description="Description Text Size" type="string" default="140%"/> <Variable name="tabs.margin.top" description="Tabs Margin Top" type="length" default="0" min="0" max="100px"/> <Variable name="tabs.margin.side" description="Tabs Side Margin" type="length" default="30px" min="0" max="100px"/> <Variable name="tabs.background.gradient" description="Tabs Background Gradient" type="url" default="url(https://resources.blogblog.com/blogblog/data/1kt/simple/gradients_light.png)"/> <Variable name="tabs.border.width" description="Tabs Border Width" type="length" default="1px" min="0" max="10px"/> <Variable name="tabs.bevel.border.width" description="Tabs Bevel Border Width" type="length" default="1px" min="0" max="10px"/> <Variable name="post.margin.bottom" description="Post Bottom Margin" type="length" default="25px" min="0" max="100px"/> <Variable name="image.border.small.size" description="Image Border Small Size" type="length" default="2px" min="0" max="10px"/> <Variable name="image.border.large.size" description="Image Border Large Size" type="length" default="5px" min="0" max="10px"/> <Variable name="page.width.selector" description="Page Width Selector" type="string" default=".region-inner"/> <Variable name="page.width" description="Page Width" type="string" default="auto"/> <Variable name="main.section.margin" description="Main Section Margin" type="length" default="15px" min="0" max="100px"/> <Variable name="main.padding" description="Main Padding" type="length" default="15px" min="0" max="100px"/> <Variable name="main.padding.top" description="Main Padding Top" type="length" default="30px" min="0" max="100px"/> <Variable name="main.padding.bottom" description="Main Padding Bottom" type="length" default="30px" min="0" max="100px"/> <Variable name="paging.background" color="#ffffff" description="Background of blog paging area" type="background" default="transparent none no-repeat scroll top center"/> <Variable name="footer.bevel" description="Bevel border length of footer" type="length" default="0" min="0" max="10px"/> <Variable name="mobile.background.overlay" description="Mobile Background Overlay" type="string" default="transparent none repeat scroll top left"/> <Variable name="mobile.background.size" description="Mobile Background Size" type="string" default="auto"/> <Variable name="mobile.button.color" description="Mobile Button Color" type="color" default="#ffffff" /> <Variable name="startSide" description="Side where text starts in blog language" type="automatic" default="left"/> <Variable name="endSide" description="Side where text ends in blog language" type="automatic" default="right"/> */ /* Content ----------------------------------------------- */ body { font: normal normal 14px Arial, Tahoma, Helvetica, FreeSans, sans-serif; color: #222222; background: #f6fbf6 none repeat scroll top left; padding: 0 40px 40px 40px; } html body .region-inner { min-width: 0; max-width: 100%; width: auto; } h2 { font-size: 22px; } a:link { text-decoration:none; color: #121fb3; } a:visited { text-decoration:none; color: #121fb3; } a:hover { text-decoration:underline; color: #1a00ff; } .body-fauxcolumn-outer .fauxcolumn-inner { background: transparent url(//www.blogblog.com/1kt/simple/body_gradient_tile_light.png) repeat scroll top left; _background-image: none; } .body-fauxcolumn-outer .cap-top { position: absolute; z-index: 1; height: 400px; width: 100%; } .body-fauxcolumn-outer .cap-top .cap-left { width: 100%; background: transparent url(//www.blogblog.com/1kt/simple/gradients_light.png) repeat-x scroll top left; _background-image: none; } .content-outer { -moz-box-shadow: 0 0 40px rgba(0, 0, 0, .15); -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, .15); -goog-ms-box-shadow: 0 0 10px #333333; box-shadow: 0 0 40px rgba(0, 0, 0, .15); margin-bottom: 1px; } .content-inner { padding: 10px 10px; } .content-inner { background-color: #ffffff; } /* Header ----------------------------------------------- */ .header-outer { background: #f6fbf7 url(//www.blogblog.com/1kt/simple/gradients_light.png) repeat-x scroll 0 -400px; _background-image: none; } .Header h1 { font: normal normal 42px Play; color: #666666; text-shadow: 1px 2px 3px rgba(0, 0, 0, .2); } .Header h1 a { color: #666666; } .Header .description { font-size: 140%; color: #666666; } .header-inner .Header .titlewrapper { padding: 22px 30px; } .header-inner .Header .descriptionwrapper { padding: 0 30px; } /* Tabs ----------------------------------------------- */ .tabs-inner .section:first-child { border-top: 0 solid #eeeeee; } .tabs-inner .section:first-child ul { margin-top: -0; border-top: 0 solid #eeeeee; border-left: 0 solid #eeeeee; border-right: 0 solid #eeeeee; } .tabs-inner .widget ul { background: #f5f5f5 url(//www.blogblog.com/1kt/simple/gradients_light.png) repeat-x scroll 0 -800px; _background-image: none; border-bottom: 1px solid #eeeeee; margin-top: 0; margin-left: -30px; margin-right: -30px; } .tabs-inner .widget li a { display: inline-block; padding: .6em 1em; font: normal normal 14px Arial, Tahoma, Helvetica, FreeSans, sans-serif; color: #999999; border-left: 1px solid #ffffff; border-right: 1px solid #eeeeee; } .tabs-inner .widget li:first-child a { border-left: none; } .tabs-inner .widget li.selected a, .tabs-inner .widget li a:hover { color: #000000; background-color: #eeeeee; text-decoration: none; } /* Columns ----------------------------------------------- */ .main-outer { border-top: 0 solid #eeeeee; } .fauxcolumn-left-outer .fauxcolumn-inner { border-right: 1px solid #eeeeee; } .fauxcolumn-right-outer .fauxcolumn-inner { border-left: 1px solid #eeeeee; } /* Headings ----------------------------------------------- */ div.widget > h2, div.widget h2.title { margin: 0 0 1em 0; font: normal bold 11px Arial, Tahoma, Helvetica, FreeSans, sans-serif; color: #000000; } /* Widgets ----------------------------------------------- */ .widget .zippy { color: #999999; text-shadow: 2px 2px 1px rgba(0, 0, 0, .1); } .widget .popular-posts ul { list-style: none; } /* Posts ----------------------------------------------- */ h2.date-header { font: normal bold 11px Arial, Tahoma, Helvetica, FreeSans, sans-serif; } .date-header span { background-color: transparent; color: transparent; padding: inherit; letter-spacing: inherit; margin: inherit; } .main-inner { padding-top: 30px; padding-bottom: 30px; } .main-inner .column-center-inner { padding: 0 15px; } .main-inner .column-center-inner .section { margin: 0 15px; } .post { margin: 0 0 25px 0; } h3.post-title, .comments h4 { font: normal normal 22px Arial, Tahoma, Helvetica, FreeSans, sans-serif; margin: .75em 0 0; } .post-body { font-size: 110%; line-height: 1.4; position: relative; } .post-body img, .post-body .tr-caption-container, .Profile img, .Image img, .BlogList .item-thumbnail img { padding: 2px; background: #ffffff; border: 1px solid #ffffff; -moz-box-shadow: 1px 1px 5px rgba(0, 0, 0, .1); -webkit-box-shadow: 1px 1px 5px rgba(0, 0, 0, .1); box-shadow: 1px 1px 5px rgba(0, 0, 0, .1); } .post-body img, .post-body .tr-caption-container { padding: 5px; } .post-body .tr-caption-container { color: #222222; } .post-body .tr-caption-container img { padding: 0; background: transparent; border: none; -moz-box-shadow: 0 0 0 rgba(0, 0, 0, .1); -webkit-box-shadow: 0 0 0 rgba(0, 0, 0, .1); box-shadow: 0 0 0 rgba(0, 0, 0, .1); } .post-header { margin: 0 0 1.5em; line-height: 1.6; font-size: 90%; } .post-footer { margin: 20px -2px 0; padding: 5px 10px; color: #666666; background-color: #f9f9f9; border-bottom: 1px solid #eeeeee; line-height: 1.6; font-size: 90%; } #comments .comment-author { padding-top: 1.5em; border-top: 1px solid #eeeeee; background-position: 0 1.5em; } #comments .comment-author:first-child { padding-top: 0; border-top: none; } .avatar-image-container { margin: .2em 0 0; } #comments .avatar-image-container img { border: 1px solid #ffffff; } /* Comments ----------------------------------------------- */ .comments .comments-content .icon.blog-author { background-repeat: no-repeat; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9sLFwMeCjjhcOMAAAD+SURBVDjLtZSvTgNBEIe/WRRnm3U8RC1neQdsm1zSBIU9VVF1FkUguQQsD9ITmD7ECZIJSE4OZo9stoVjC/zc7ky+zH9hXwVwDpTAWWLrgS3QAe8AZgaAJI5zYAmc8r0G4AHYHQKVwII8PZrZFsBFkeRCABYiMh9BRUhnSkPTNCtVXYXURi1FpBDgArj8QU1eVXUzfnjv7yP7kwu1mYrkWlU33vs1QNu2qU8pwN0UpKoqokjWwCztrMuBhEhmh8bD5UDqur75asbcX0BGUB9/HAMB+r32hznJgXy2v0sGLBcyAJ1EK3LFcbo1s91JeLwAbwGYu7TP/3ZGfnXYPgAVNngtqatUNgAAAABJRU5ErkJggg==); } .comments .comments-content .loadmore a { border-top: 1px solid #999999; border-bottom: 1px solid #999999; } .comments .comment-thread.inline-thread { background-color: #f9f9f9; } .comments .continue { border-top: 2px solid #999999; } /* Accents ---------------------------------------------- */ .section-columns td.columns-cell { border-left: 1px solid #eeeeee; } .blog-pager { background: transparent none no-repeat scroll top center; } .blog-pager-older-link, .home-link, .blog-pager-newer-link { background-color: #ffffff; padding: 5px; } .footer-outer { border-top: 0 dashed #bbbbbb; } /* Mobile ----------------------------------------------- */ body.mobile { background-size: auto; } .mobile .body-fauxcolumn-outer { background: transparent none repeat scroll top left; } .mobile .body-fauxcolumn-outer .cap-top { background-size: 100% auto; } .mobile .content-outer { -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, .15); box-shadow: 0 0 3px rgba(0, 0, 0, .15); } .mobile .tabs-inner .widget ul { margin-left: 0; margin-right: 0; } .mobile .post { margin: 0; } .mobile .main-inner .column-center-inner .section { margin: 0; } .mobile .date-header span { padding: 0.1em 10px; margin: 0 -10px; } .mobile h3.post-title { margin: 0; } .mobile .blog-pager { background: transparent none no-repeat scroll top center; } .mobile .footer-outer { border-top: none; } .mobile .main-inner, .mobile .footer-inner { background-color: #ffffff; } .mobile-index-contents { color: #222222; } .mobile-link-button { background-color: #121fb3; } .mobile-link-button a:link, .mobile-link-button a:visited { color: #ffffff; } .mobile .tabs-inner .section:first-child { border-top: none; } .mobile .tabs-inner .PageList .widget-content { background-color: #eeeeee; color: #000000; border-top: 1px solid #eeeeee; border-bottom: 1px solid #eeeeee; } .mobile .tabs-inner .PageList .widget-content .pagelist-arrow { border-left: 1px solid #eeeeee; } .content-outer { max-width: 1400px !important; } /* fix header */ #header-inner { width: 100% !important; background-position: right !important; } .titlewrapper { padding: 11px 30px 0 !important; } .descriptionwrapper { margin-bottom: 0 !important; } .description { font-size: 120% !important; } /* suppress things */ .date-header { display: none; } #Attribution1 { display: none; } .post-author, .post-timestamp, .reaction-buttons { display: none; } /* h2: sidebar titles */ /* h3: post title */ .post-title , .entry-title { font-size: 180% !important; margin-top: 0 !important; } .entry-title a:link, .entry-title a:visited, .entry-title a:active{ color: #a03; } #main h2 { color:#333; margin-bottom:.4em; margin-top: 13px; font-size:140%; } #main h3 { color:#333; margin-bottom:.4em; margin-top: 13px; font-size:110%; } #main h4 { color:#333; margin-bottom:.5em; } #sidebar-right-1 a:link, #sidebar-right-1 a:visited, #sidebar-right-1 a:active { color: #666; } #sidebar-right-1 h2 { font-size: 100%; color: #666; } /* disable image box */ element.style { } table.chargers img { height: 18px; } table.chargers img { height: 18px; } .post-body img, .post-body .tr-caption-container { padding: 5px; } .post-body img, .post-body .tr-caption-container, .Profile img, .Image img, .BlogList .item-thumbnail img { padding: 0; background: #ffffff; border: none; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; } /* Special items */ a:link img.hilite, a:visited img.hilite { color: #fff; } a:hover img.hilite, a:hover img.hilite2 { color: #f66; } a:active img.hilite { color: #33c; } .hilite {cursor:zoom-in} pre {color:#000000;border:1px solid #000000;} pre.repl { background-color:#e0e0f0; font-size:120%;} pre.arc { background-color:#e0e0f0; font-size:120%;} pre.code { background-color:#e0f0e0; font-size:120%; white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word;text-wrap:unrestricted;} code { font-size: 100%;} blockquote { font-size: 110%; background: transparent url("//static.righto.com/images/blockquote.gif") no-repeat 0 0; margin: 20px 0px; padding: 0px 40px;} div.cite {font-size: .8em;.; font-style: italic; color: #888; margin-bottom: 9px;} a.ref { color: gray;vertical-align: super; text-decoration: none; font-size:60%;margin-left: 2px;} a img.hilite { border: 1px solid; color: #888; z-index: 2; } a img.hilite2, a:active img.hilite2 { border: 1px solid; color: #f6fbf6; } table.chargers { border-width: 1px; border-spacing: 2px; border-style: outset; border-color: gray; border-collapse: collapse; background-color: white; } table.chargers th.maker { padding-right: 5px; text-align: right; } table.chargers th { border-width: 1px; padding: 3px; border-style: inset; border-color: gray; background-color: white; text-align: center; } table.chargers img { height: 18px; } table.chargers td { text-align: center; border-width: 1px; padding: 2px 8px; border-style: inset; border-color: gray; background-color: white; } --></style> <style id='template-skin-1' type='text/css'><!-- body { min-width: 750px; } .content-outer, .content-fauxcolumn-outer, .region-inner { min-width: 750px; max-width: 750px; _width: 750px; } .main-inner .columns { padding-left: 0px; padding-right: 240px; } .main-inner .fauxcolumn-center-outer { left: 0px; right: 240px; /* IE6 does not respect left and right together */ _width: expression(this.parentNode.offsetWidth - parseInt("0px") - parseInt("240px") + 'px'); } .main-inner .fauxcolumn-left-outer { width: 0px; } .main-inner .fauxcolumn-right-outer { width: 240px; } .main-inner .column-left-outer { width: 0px; right: 100%; margin-left: -0px; } .main-inner .column-right-outer { width: 240px; margin-right: -240px; } #layout { min-width: 0; } #layout .content-outer { min-width: 0; width: 800px; } #layout .region-inner { min-width: 0; width: auto; } --></style> <meta content='width=device-width, initial-scale=1.0, maximum-scale=12.0, minimum-scale=.25, user-scalable=yes' name='viewport'/> <meta content='mw8ww70r3jW0GzXY6j1d' name='follow_it-verification-code'/> <link href='https://www.blogger.com/dyn-css/authorization.css?targetBlogID=6264947694886887540&zx=6fd23a04-bc1a-4aed-b46d-611afb4481ef' media='none' onload='if(media!='all')media='all'' rel='stylesheet'/><noscript><link href='https://www.blogger.com/dyn-css/authorization.css?targetBlogID=6264947694886887540&zx=6fd23a04-bc1a-4aed-b46d-611afb4481ef' rel='stylesheet'/></noscript> <meta name='google-adsense-platform-account' content='ca-host-pub-1556223355139109'/> <meta name='google-adsense-platform-domain' content='blogspot.com'/> </head> <body class='loading'> <div class='navbar no-items section' id='navbar'> </div> <div class='body-fauxcolumns'> <div class='fauxcolumn-outer body-fauxcolumn-outer'> <div class='cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left'> <div class='fauxborder-right'></div> <div class='fauxcolumn-inner'> </div> </div> <div class='cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> </div> <div class='content'> <div class='content-fauxcolumns'> <div class='fauxcolumn-outer content-fauxcolumn-outer'> <div class='cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left'> <div class='fauxborder-right'></div> <div class='fauxcolumn-inner'> </div> </div> <div class='cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> </div> <div class='content-outer'> <div class='content-cap-top cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left content-fauxborder-left'> <div class='fauxborder-right content-fauxborder-right'></div> <div class='content-inner'> <header> <div class='header-outer'> <div class='header-cap-top cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left header-fauxborder-left'> <div class='fauxborder-right header-fauxborder-right'></div> <div class='region-inner header-inner'> <div class='header section' id='header'><div class='widget Header' data-version='1' id='Header1'> <div id='header-inner' style='background-image: url("https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-4KXwYe0lQ4HFzhAye9vvRlij2ZYvMbfPCnqEE__1o85Fjo3XgefxJQhWRdwR3EzNWNMWT3yMaj2QZaT9GazqQx3C6oWa3-hBNlRHG7f-Oib-lv1Wq_C2_A0rt8xZgs87iNqzRVKK7H0A/s800/background.jpg"); background-position: left; width: 550px; min-height: 105px; _height: 105px; background-repeat: no-repeat; '> <div class='titlewrapper' style='background: transparent'> <h1 class='title' style='background: transparent; border-width: 0px'> <a href='http://www.righto.com/'> Ken Shirriff's blog </a> </h1> </div> <div class='descriptionwrapper'> <p class='description'><span>Computer history, restoring vintage computers, IC reverse engineering, and whatever</span></p> </div> </div> </div></div> </div> </div> <div class='header-cap-bottom cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> </header> <div class='tabs-outer'> <div class='tabs-cap-top cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left tabs-fauxborder-left'> <div class='fauxborder-right tabs-fauxborder-right'></div> <div class='region-inner tabs-inner'> <div class='tabs no-items section' id='crosscol'></div> <div class='tabs no-items section' id='crosscol-overflow'></div> </div> </div> <div class='tabs-cap-bottom cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> <div class='main-outer'> <div class='main-cap-top cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left main-fauxborder-left'> <div class='fauxborder-right main-fauxborder-right'></div> <div class='region-inner main-inner'> <div class='columns fauxcolumns'> <div class='fauxcolumn-outer fauxcolumn-center-outer'> <div class='cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left'> <div class='fauxborder-right'></div> <div class='fauxcolumn-inner'> </div> </div> <div class='cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> <div class='fauxcolumn-outer fauxcolumn-left-outer'> <div class='cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left'> <div class='fauxborder-right'></div> <div class='fauxcolumn-inner'> </div> </div> <div class='cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> <div class='fauxcolumn-outer fauxcolumn-right-outer'> <div class='cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left'> <div class='fauxborder-right'></div> <div class='fauxcolumn-inner'> </div> </div> <div class='cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> <!-- corrects IE6 width calculation --> <div class='columns-inner'> <div class='column-center-outer'> <div class='column-center-inner'> <div class='main section' id='main'><div class='widget Blog' data-version='1' id='Blog1'> <div class='blog-posts hfeed'> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='https://static.righto.com/images/globus-gearing/globus-w600.jpg' itemprop='image_url'/> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='8868607841305902549' itemprop='postId'/> <a name='8868607841305902549'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2023/03/reverse-engineering-globus-ink-soviet.html'>Reverse-engineering the Globus INK, a Soviet spaceflight navigation computer</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-8868607841305902549' itemprop='description articleBody'> <style> .hilite {cursor:zoom-in} </style> <p>One of the most interesting navigation instruments onboard Soyuz spacecraft was the Globus INK,<span id="fnref:ink"><a class="ref" href="#fn:ink">1</a></span> which used a rotating globe to indicate the spacecraft's position above the Earth. This electromechanical analog computer used an elaborate system of gears, cams, and differentials to compute the spacecraft's position. The globe rotates in two dimensions: it spins end-over-end to indicate the spacecraft's orbit, while the globe's hemispheres rotate according to the Earth's daily rotation around its axis.<span id="fnref:day"><a class="ref" href="#fn:day">2</a></span> The spacecraft's position above the Earth was represented by the fixed crosshairs on the plastic dome. The Globus also has latitude and longitude dials next to the globe to show the position numerically, while the light/shadow dial below the globe indicated when the spacecraft would enter or leave the Earth's shadow.</p> <p><a href="https://static.righto.com/images/globus-gearing/globus.jpg"><img alt="The INK-2S "Globus" space navigation indicator." class="hilite" height="457" src="https://static.righto.com/images/globus-gearing/globus-w600.jpg" title="The INK-2S "Globus" space navigation indicator." width="600" /></a><div class="cite">The INK-2S "Globus" space navigation indicator.</div></p> <p>Opening up the Globus reveals that it is packed with complicated gears and mechanisms. It's amazing that this mechanical technology was used from the 1960s into the 21st century. But what are all those gears doing? How can orbital functions be implemented with gears? To answer these questions, I reverse-engineered the Globus and traced out its system of gears.</p> <p><a href="https://static.righto.com/images/globus-gearing/opened-end.jpg"><img alt="The Globus with the case removed, showing the complex gearing inside." class="hilite" height="496" src="https://static.righto.com/images/globus-gearing/opened-end-w500.jpg" title="The Globus with the case removed, showing the complex gearing inside." width="500" /></a><div class="cite">The Globus with the case removed, showing the complex gearing inside.</div></p> <p>The diagram below summarizes my analysis. The Globus is an analog computer that represents values by rotating shafts by particular amounts. These rotations control the globe and the indicator dials. The flow of these rotational signals is shown by the lines on the diagram. The computation is based around addition, performed by ten differential gear assemblies. On the diagram, each "⨁" symbol indicates one of these differential gear assemblies. Other gears connect the components while scaling the signals through various gear ratios. Complicated functions are implemented with three specially-shaped cams. In the remainder of this blog post, I will break this diagram down into functional blocks and explain how the Globus operates.</p> <p><a href="https://static.righto.com/images/globus-gearing/diagram.png"><img alt="This diagram shows the interconnections of the gear network in the Globus." class="hilite" height="370" src="https://static.righto.com/images/globus-gearing/diagram-w700.png" title="This diagram shows the interconnections of the gear network in the Globus." width="700" /></a><div class="cite">This diagram shows the interconnections of the gear network in the Globus.</div></p> <!-- ## The overall network I've created the diagram below to show how the mechanical components of the Globus are connected. This diagram focuses on the ten differentials, numbered 1 through 10. The orbital motion is controlled by differentials 1 through 3. This block is driven by the orbit solenoid, which provides a small rotation once every second. The cam provides an adjustment to the orbital speed, which varies depending on altitude. The orbit knob on the front panel allows the position to be adjusted by hand. Differential 4 handles this input and produces the orbital position signal. For the "landing position" mode, differential 5 allows the landing motor to rotate the position. The output from differential 5 indicates the orbital position and rotates the globe. It also rotates a potentiometer to provide an output signal and drives the light/shadow wheel. The second motion is the Earth's rotation around its axis. This is driven by a second solenoid that pulses onces a second. There is also a knob to manually rotate the globe around its axis. These signals are combined by differential 6. Differential 7 adds the signal from the landing motor and differential 8 adds the signal from the orbital rotation; these cancel out the mechanical effect of the orbital rotation on the earth rotation. Differentials 9 and 10 compute the longitude, combining the effect of the Earth's rotation with the orbital motion, corrected by a cam. --> <p>For all its complexity, though, the functionality of the Globus is pretty limited. It only handles a fixed orbit at a specific angle, and treats the orbit as circular. The Globus does not have any navigation input such as an inertial measurement unit (IMU). Instead, the cosmonauts configured the Globus by turning knobs to set the spacecraft's initial position and orbital period. From there, the Globus simply projected the current position of the spacecraft forward, essentially <a href="https://en.wikipedia.org/wiki/Dead_reckoning">dead reckoning</a>.</p> <p><a href="https://static.righto.com/images/globus-gearing/gears.jpg"><img alt="A closeup of the gears inside the Globus." class="hilite" height="374" src="https://static.righto.com/images/globus-gearing/gears-w500.jpg" title="A closeup of the gears inside the Globus." width="500" /></a><div class="cite">A closeup of the gears inside the Globus.</div></p> <h2>The globe</h2> <p>On seeing the Globus, one might wonder how the globe is rotated. It may seem that the globe must be free-floating so it can rotate in two axes. Instead, a clever mechanism attaches the globe to the unit. The key is that the globe's equator is a solid piece of metal that rotates around the horizontal axis of the unit. A second gear mechanism inside the globe rotates the globe around the North-South axis. The two rotations are controlled by concentric shafts that are fixed to the unit. Thus, the globe has two rotational degrees of freedom, even though it is attached at both ends.</p> <p>The photo below shows the frame that holds and controls the globe. The dotted axis is fixed horizontally in the unit and rotations are fed through the two gears at the left. One gear rotates the globe and frame around the dotted axis, while the gear train causes the globe to rotate around the vertical polar axis (while the equator remains fixed).</p> <p><a href="https://static.righto.com/images/globus-gearing/axis.jpg"><img alt="The axis of the globe is at 51.8° to support that orbital inclination." class="hilite" height="331" src="https://static.righto.com/images/globus-gearing/axis-w500.jpg" title="The axis of the globe is at 51.8° to support that orbital inclination." width="500" /></a><div class="cite">The axis of the globe is at 51.8° to support that orbital inclination.</div></p> <p>The angle above is 51.8° which is very important: this is the inclination of the standard Soyuz orbit. As a result, simply rotating the globe around the dotted line causes the crosshair to trace the orbit.<span id="fnref:orbit"><a class="ref" href="#fn:orbit">3</a></span> Rotating the two halves of the globe around the poles yields the different paths over the Earth's surface as the Earth rotates. An important consequence of this design is that the Globus only supports a circular orbit at a fixed angle.</p> <h2>Differential gear mechanism</h2> <p>The primary mathematical element of the Globus is the differential gear mechanism, which can perform addition or subtraction. A differential gear takes two rotations as inputs and produces the (scaled) sum of the rotations as the output. The photo below shows one of the differential mechanisms. In the middle, the spider gear assembly (red box) consists of two bevel gears that can spin freely on a vertical shaft. The spider gear assembly as a whole is attached to a horizontal shaft, called the spider shaft. At the right, the spider shaft is attached to a spur gear (a gear with straight-cut teeth). The spider gear assembly, the spider shaft, and the spider's spur gear rotate together as a unit.</p> <p><a href="https://static.righto.com/images/globus-gearing/differential-diagram.jpg"><img alt="Diagram showing the components of a differential gear mechanism." class="hilite" height="384" src="https://static.righto.com/images/globus-gearing/differential-diagram-w500.jpg" title="Diagram showing the components of a differential gear mechanism." width="500" /></a><div class="cite">Diagram showing the components of a differential gear mechanism.</div></p> <p>At the left and right are two end gear assemblies (yellow). The end gear is a bevel gear with angled teeth to mesh with the spider gears. Each end gear is locked to a spur gear and these gears spin freely on the horizontal spider shaft. In total, there are three spur gears: two connected to the end gears and one connected to the spider assembly. In the diagrams, I'll use the symbol below to represent the differential gear assembly: the end gears are symmetric on the top and bottom, with the spider shaft on the side. Any of the three spur gears can be used as an output, with the other two serving as inputs.</p> <p><a href="https://static.righto.com/images/globus-gearing/differential-symbol.jpg"><img alt="The symbol for the differential gear assembly." class="hilite" height="117" src="https://static.righto.com/images/globus-gearing/differential-symbol-w120.jpg" title="The symbol for the differential gear assembly." width="120" /></a><div class="cite">The symbol for the differential gear assembly.</div></p> <p>To understand the behavior of the differential, suppose the two end gears are driven in the same direction at the same rate, say upwards.<span id="fnref:directions"><a class="ref" href="#fn:directions">4</a></span> These gears will push on the spider gears and rotate the spider gear assembly, with the entire differential rotating as a fixed unit. On the other hand, suppose the two end gears are driven in opposite directions. In this case, the spider gears will spin on their shaft, but the spider gear assembly will remain stationary. In either case, the spider gear assembly motion is the average of the two end gear rotations, that is, the sum of the two rotations divided by 2. (I'll ignore the factor of 2 since I'm ignoring all the gear ratios.) If the operation of the differential is still confusing, <a href="https://youtu.be/mQhmmTX5f9Y?t=68">this vintage Navy video</a> has a detailed explanation.</p> <h2>The controls and displays</h2> <p>The diagram below shows the controls and displays of the Globus. The rotating globe is the centerpiece of the unit. Its plastic cover has a crosshair that represents the spacecraft's position above the Earth's surface. Surrounding the globe itself are dials that show the longitude, latitude, and the time before entering light and shadow. The cosmonauts manually initialize the globe position with the concentric globe rotation knobs: one rotates the globe along the orbital path while the other rotates the hemispheres. The mode switch at the top selects between the landing position mode, the standard Earth orbit mode, and turning off the unit. The orbit time adjustment configures the orbital time period in minutes while the orbit counter below it counts the number of orbits. Finally, the landing point angle sets the distance to the landing point in degrees of orbit.</p> <p><a href="https://static.righto.com/images/globus-gearing/globus-labeled.jpg"><img alt="The Globus with the controls labeled." class="hilite" height="466" src="https://static.righto.com/images/globus-gearing/globus-labeled-w700.jpg" title="The Globus with the controls labeled." width="700" /></a><div class="cite">The Globus with the controls labeled.</div></p> <h2>Computing the orbit time</h2> <p>The primary motion of the Globus is the end-over-end rotation of the globe showing the movement of the spacecraft in orbit. The orbital motion is powered by a solenoid at the top of the Globus that receives pulses once a second and advances a ratchet wheel (<a href="https://twitter.com/kenshirriff/status/1628118949421363201">video</a>).<span id="fnref:torque"><a class="ref" href="#fn:torque">5</a></span> This wheel is connected to a complicated cam and differential system to provide the orbital motion.</p> <p><a href="https://static.righto.com/images/globus-gearing/orbit-solenoid.jpg"><img alt="The orbit solenoid (green) has a ratchet that rotates the gear to the right. The shaft connects it to differential gear assembly 1 at the bottom right." class="hilite" height="404" src="https://static.righto.com/images/globus-gearing/orbit-solenoid-w500.jpg" title="The orbit solenoid (green) has a ratchet that rotates the gear to the right. The shaft connects it to differential gear assembly 1 at the bottom right." width="500" /></a><div class="cite">The orbit solenoid (green) has a ratchet that rotates the gear to the right. The shaft connects it to differential gear assembly 1 at the bottom right.</div></p> <p>Each orbit takes about 92 minutes, but the orbital time can be adjusted by a few minutes in steps of 0.01 minutes<span id="fnref:time"><a class="ref" href="#fn:time">6</a></span> to account for changes in altitude. The Globus is surprisingly inflexible and this is the only orbital parameter that can be adjusted.<span id="fnref:parameters"><a class="ref" href="#fn:parameters">7</a></span> The orbital period is adjusted by the three-position orbit time switch, which points to the minutes, tenths, or hundredths. Turning the central knob adjusts the indicated period dial.</p> <p>The problem is how to generate the variable orbital rotation speed from the fixed speed of the solenoid. The solution is a special cam, shaped like a cone with a spiral cross-section. Three followers ride on the cam, so as the cam rotates, the follower is pushed outward and rotates on its shaft. If the follower is near the narrow part of the cam, it moves over a small distance and has a small rotation. But if the follower is near the wide part of the cam, it moves a larger distance and has a larger rotation. Thus, by moving the follower to a particular point on the cam, the rotational speed of the follower is selected. One follower adjusts the speed based on the minutes setting with others for the tenths and hundredths of minutes.</p> <p><a href="https://static.righto.com/images/globus-gearing/cone-diagram.jpg"><img alt="A diagram showing the orbital speed control mechanism. The cone has three followers, but only two are visible from this angle. The "transmission" gears are moved in and out by the outer knob to select which follower is adjusted by the inner knob." class="hilite" height="533" src="https://static.righto.com/images/globus-gearing/cone-diagram-w600.jpg" title="A diagram showing the orbital speed control mechanism. The cone has three followers, but only two are visible from this angle. The "transmission" gears are moved in and out by the outer knob to select which follower is adjusted by the inner knob." width="600" /></a><div class="cite">A diagram showing the orbital speed control mechanism. The cone has three followers, but only two are visible from this angle. The "transmission" gears are moved in and out by the outer knob to select which follower is adjusted by the inner knob.</div></p> <p>Of course, the cam can't spiral out forever. Instead, at the end of one revolution, its cross-section drops back sharply to the starting diameter. This causes the follower to snap back to its original position. To prevent this from jerking the globe backward, the follower is connected to the differential gearing via a slip clutch and ratchet. Thus, when the follower snaps back, the ratchet holds the drive shaft stationary. The drive shaft then continues its rotation as the follower starts cycling out again. Each shaft output is accordingly a (mostly) smooth rotation at a speed that depends on the position of the follower.</p> <p><a href="https://static.righto.com/images/globus-gearing/diagram-orbit.png"><img alt="A cam-based system adjusts the orbital speed using three differential gear assemblies." class="hilite" height="353" src="https://static.righto.com/images/globus-gearing/diagram-orbit-w500.png" title="A cam-based system adjusts the orbital speed using three differential gear assemblies." width="500" /></a><div class="cite">A cam-based system adjusts the orbital speed using three differential gear assemblies.</div></p> <p>The three adjustment signals are scaled by gear ratios to provide the appropriate contribution to the rotation. As shown above, the adjustments are added to the solenoid output by three differentials to generate the orbit rotation signal, output from differential 3.<span id="fnref:loop"><a class="ref" href="#fn:loop">8</a></span> This signal also drives the odometer-like orbit counter on the front of the Globus. The diagram below shows how the components are arranged, as viewed from the back.</p> <p><a href="https://static.righto.com/images/globus-gearing/diagram-back2.jpg"><img alt="A back view of the Globus showing the orbit components." class="hilite" height="584" src="https://static.righto.com/images/globus-gearing/diagram-back2-w600.jpg" title="A back view of the Globus showing the orbit components." width="600" /></a><div class="cite">A back view of the Globus showing the orbit components.</div></p> <h2>Displaying the orbit rotation</h2> <p>Since the Globus doesn't have any external position input such as inertial guidance, it must be initialized by the cosmonauts. A knob on the front of the Globus provides manual adjustment of the orbital position. Differential 4 adds the knob signal to the orbit output discussed above.</p> <p><a href="https://static.righto.com/images/globus-gearing/diagram-orbit2.png"><img alt="The orbit controls drive the globe's motion." class="hilite" height="334" src="https://static.righto.com/images/globus-gearing/diagram-orbit2-w700.png" title="The orbit controls drive the globe's motion." width="700" /></a><div class="cite">The orbit controls drive the globe's motion.</div></p> <p>The Globus has a "landing point" mode where the globe is rapidly rotated through a fraction of an orbit to indicate where the spacecraft would land if the retro-rockets were fired. Turning the mode switch caused the globe to rotate until the landing position was under the crosshairs and the cosmonauts could evaluate the suitability of this landing site. This mode is implemented with a landing position motor that provides the rapid rotation. This motor also rotates the globe back to the orbital position. The motor is driven through an electronics board with relays and a transistor, controlled by limit switches. I discussed the electronics in a <a href="https://www.righto.com/2023/03/reverse-engineering-electronics-in.html">previous post</a> so I won't go into more details here. The landing position motor feeds into the orbit signal through differential 5, producing the final orbit signal.</p> <p><a href="https://static.righto.com/images/globus-gearing/landing-motor.jpg"><img alt="The landing position motor and its associated gearing. The motor speed is geared down and then fed through a worm gear (upper center)." class="hilite" height="382" src="https://static.righto.com/images/globus-gearing/landing-motor-w400.jpg" title="The landing position motor and its associated gearing. The motor speed is geared down and then fed through a worm gear (upper center)." width="400" /></a><div class="cite">The landing position motor and its associated gearing. The motor speed is geared down and then fed through a worm gear (upper center).</div></p> <p>The orbit signal from differential 5 is used in several ways. Most importantly, the orbit signal provides the end-over-end rotation of the globe to indicate the spacecraft's travel in orbit. As discussed earlier, this is accomplished by rotating the globe's metal frame around the horizontal axis. The orbital signal also rotates a potentiometer to provide an electrical indication of the orbital position to other spacecraft systems.</p> <h2>The light/shadow indicator</h2> <p>Docking a spacecraft is a tricky endeavor, best performed in daylight, so it is useful to know how much time remains until the spacecraft enters the Earth's shadow. The light/shadow dial under the globe provides this information. This display consists of two nested wheels. The outer wheel is white and has two quarters removed. Through these gaps, the partially-black inner wheel is exposed, which can be adjusted to show 0% to 50% dark. This display is rotated by the orbital signal, turning half a revolution per orbit. As the spacecraft orbits, this dial shows the light/shadow transition and the time to the transistion.<span id="fnref:scale"><a class="ref" href="#fn:scale">9</a></span></p> <p><a href="https://static.righto.com/images/globus-gearing/light-shadow-dials.jpg"><img alt="The light/shadow indicator, viewed from the underside of the Globus. The shadow indicator has been set to 35% shadow. Near the hub, a pin restricts motion of the inner wheel relative to the outer wheel." class="hilite" height="348" src="https://static.righto.com/images/globus-gearing/light-shadow-dials-w500.jpg" title="The light/shadow indicator, viewed from the underside of the Globus. The shadow indicator has been set to 35% shadow. Near the hub, a pin restricts motion of the inner wheel relative to the outer wheel." width="500" /></a><div class="cite">The light/shadow indicator, viewed from the underside of the Globus. The shadow indicator has been set to 35% shadow. Near the hub, a pin restricts motion of the inner wheel relative to the outer wheel.</div></p> <p>You might expect the orbit to be in the dark 50% of the time, but because the spacecraft is about 200 km above the Earth's surface, it will sometimes be illuminated when the surface of the Earth underneath is dark.<span id="fnref:iss"><a class="ref" href="#fn:iss">10</a></span> In the ground track below, the dotted part of the track is where the spacecraft is in the Earth's shadow; this is considerably less than 50%. Also note that the end of the orbit doesn't match up with the beginning, due to the Earth's rotation during the orbit.</p> <p><a href="https://static.righto.com/images/globus-gearing/orbitdisplay4.png"><img alt="Ground track of an Apollo-Soyuz Test Project orbit, corresponding to this Globus. Image courtesy of heavens-above.com." class="hilite" height="300" src="https://static.righto.com/images/globus-gearing/orbitdisplay4-w600.png" title="Ground track of an Apollo-Soyuz Test Project orbit, corresponding to this Globus. Image courtesy of heavens-above.com." width="600" /></a><div class="cite">Ground track of an Apollo-Soyuz Test Project orbit, corresponding to this Globus. Image courtesy of <a href="https://www.heavens-above.com/orbit.aspx?satid=08032">heavens-above.com</a>.</div></p> <h2>The latitude indicator</h2> <p>The latitude indicator to the left of the globe shows the spacecraft's latitude. The map above shows how the latitude oscillates between 51.8°N and 51.8°S, corresponding to the launch inclination angle. Even though the path around the globe is a straight (circular) line, the orbit appears roughly sinusoidal when projected onto the map.<span id="fnref:sinusoid"><a class="ref" href="#fn:sinusoid">11</a></span> The exact latitude is a surprisingly complicated function of the orbital position.<span id="fnref:formulas"><a class="ref" href="#fn:formulas">12</a></span> This function is implemented by a cam that is attached to the globe. The varying radius of the cam corresponds to the function. A follower tracks the profile of the cam and rotates the latitude display wheel accordingly, providing the non-linear motion.</p> <p><a href="https://static.righto.com/images/globus-gearing/latitude-cam.jpg"><img alt="A cam is attached to the globe and rotates with the globe." class="hilite" height="353" src="https://static.righto.com/images/globus-gearing/latitude-cam-w400.jpg" title="A cam is attached to the globe and rotates with the globe." width="400" /></a><div class="cite">A cam is attached to the globe and rotates with the globe.</div></p> <h2>The Earth's rotation</h2> <p>The second motion of the globe is the Earth's daily rotation around its axis, which I'll call the Earth rotation. The Earth rotation is fed into the globe through the outer part of a concentric shaft, while the orbital rotation is provided through the inner shaft. The Earth rotation is transferred through three gears to the equatorial frame, where an internal mechanism rotates the hemispheres. There's a complication, though: if the globe's orbital shaft turns while the Earth rotation shaft remains stationary, the frame will rotate, causing the gears to turn and the hemispheres to rotate. In other words, keeping the hemispheres stationary requires the Earth shaft to rotate with the orbit shaft.</p> <p><a href="https://static.righto.com/images/globus-gearing/globe-closeup.jpg"><img alt="A closeup of the gear mechanisms that drive the Globus, showing the concentric shafts that control the two rotations." class="hilite" height="464" src="https://static.righto.com/images/globus-gearing/globe-closeup-w400.jpg" title="A closeup of the gear mechanisms that drive the Globus, showing the concentric shafts that control the two rotations." width="400" /></a><div class="cite">A closeup of the gear mechanisms that drive the Globus, showing the concentric shafts that control the two rotations.</div></p> <p>The Globus solves this problem by adding the orbit rotation to the Earth rotation, as shown in the diagram below, using differentials 7 and 8. Differential 8 adds the normal orbit rotation, while differential 7 adds the orbit rotation due to the landing motor.<span id="fnref:landing"><a class="ref" href="#fn:landing">14</a></span></p> <p><a href="https://static.righto.com/images/globus-gearing/diagram-earth.png"><img alt="The mechanism to compute the Earth's rotation around its axis." class="hilite" height="391" src="https://static.righto.com/images/globus-gearing/diagram-earth-w350.png" title="The mechanism to compute the Earth's rotation around its axis." width="350" /></a><div class="cite">The mechanism to compute the Earth's rotation around its axis.</div></p> <p>The Earth motion is generated by a second solenoid (below) that is driven with one pulse per second.<span id="fnref:solenoid"><a class="ref" href="#fn:solenoid">13</a></span> This motion is simpler than the orbit motion because it has a fixed rate. The "Earth" knob on the front of the Globus permits manual rotation around the Earth's axis. This signal is combined with the solenoid signal by differential 6. The sum from the three differentials is fed into the globe, rotating the hemispheres around their axis.</p> <p><a href="https://static.righto.com/images/globus-gearing/earth-solenoid.jpg"><img alt="This solenoid, ratchet, and gear on the underside of the Globus drive the Earth rotation." class="hilite" height="286" src="https://static.righto.com/images/globus-gearing/earth-solenoid-w350.jpg" title="This solenoid, ratchet, and gear on the underside of the Globus drive the Earth rotation." width="350" /></a><div class="cite">This solenoid, ratchet, and gear on the underside of the Globus drive the Earth rotation.</div></p> <p>The solenoid and differentials are visible from the underside of the Globus. The diagram below labels these components as well as other important components.</p> <p><a href="https://static.righto.com/images/globus-gearing/diagram-underside.jpg"><img alt="The underside of the Globus." class="hilite" height="665" src="https://static.righto.com/images/globus-gearing/diagram-underside-w700.jpg" title="The underside of the Globus." width="700" /></a><div class="cite">The underside of the Globus.</div></p> <h2>The longitude display</h2> <p><a href="https://static.righto.com/images/globus-gearing/longitude-cam.jpg"><img alt="The longitude cam and the followers that track its radius." class="hilite" height="383" src="https://static.righto.com/images/globus-gearing/longitude-cam-w350.jpg" title="The longitude cam and the followers that track its radius." width="350" /></a><div class="cite">The longitude cam and the followers that track its radius.</div></p> <p>The longitude display is more complicated than the latitude display because it depends on both the Earth rotation and the orbit rotation. Unlike the latitude, the longitude doesn't oscillate but increases. The longitude increases by 360° every orbit according to a complicated formula describing the projection of the orbit onto the globe. Most of the time, the increase is small, but when crossing near the poles, the longitude changes rapidly. The Earth's rotation provides a smaller but steady negative change to the longitude.</p> <p><a href="https://static.righto.com/images/globus-gearing/diagram-earth2.png"><img alt="The computation of the longitude." class="hilite" height="245" src="https://static.righto.com/images/globus-gearing/diagram-earth2-w220.png" title="The computation of the longitude." width="220" /></a><div class="cite">The computation of the longitude.</div></p> <p>The diagram above shows how the longitude is computed by combining the Earth rotation with the orbit rotation. Differential 9 adds the linear effect of the orbit on longitude (360° per orbit) and subtracts the effect of the Earth's rotation (360° per day). The nonlinear effect of the orbit is computed by a cam that is rotated by the orbit signal. The shape of the cam is picked up and fed into differential 10, computing the longitude that is displayed on the dial. The differentials, cam, and dial are visible from the back of the Globus (below).</p> <p><a href="https://static.righto.com/images/globus-gearing/diagram-back.jpg"><img alt="A closeup of the differentials from the back of the Globus." class="hilite" height="621" src="https://static.righto.com/images/globus-gearing/diagram-back-w450.jpg" title="A closeup of the differentials from the back of the Globus." width="450" /></a><div class="cite">A closeup of the differentials from the back of the Globus.</div></p> <p>The time-lapse video below demonstrates the behavior of the rotating displays. The latitude display on the left oscillates between 51.8°N and 51.8°S. The longitude display at the top advances at a changing rate. Near the equator, it advances slowly, while it accelerates near the poles. The light/shadow display at the bottom rotates at a constant speed, completing half a revolution (one light/shadow cycle) per orbit.</p> <iframe width="560" height="315" src="https://www.youtube.com/embed/nDHtJy9cpC0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe> <h2>Conclusions</h2> <p>The Globus INK is a remarkable piece of machinery, an analog computer that calculates orbits through an intricate system of gears, cams, and differentials. It provided astronauts with a high-resolution, full-color display of the spacecraft's position, way beyond what an electronic space computer could provide in the 1960s.</p> <p>The drawback of the Globus is that its functionality is limited. Its parameters must be manually configured: the spacecraft's starting position, the orbital speed, the light/shadow regions, and the landing angle. It doesn't take any external guidance inputs, such as an IMU (inertial measurement unit), so it's not particularly accurate. Finally, it only supports a circular orbit at a fixed angle. While a more modern digital display lacks the physical charm of a rotating globe, the digital solution provides much more capability.</p> <p>I recently wrote blog posts providing a <a href="https://www.righto.com/2023/01/inside-globus-ink-mechanical-navigation.html">Globus overview</a> and <a href="https://www.righto.com/2023/03/reverse-engineering-electronics-in.html">the Globus electronics</a>. Follow me on Twitter <a href="https://twitter.com/kenshirriff">@kenshirriff</a> or <a href="http://www.righto.com/feeds/posts/default">RSS</a> for updates. I've also started experimenting with Mastodon recently as <a href="https://oldbytes.space/@kenshirriff">@<span class="__cf_email__" data-cfemail="8ce7e9e2ffe4e5fefee5eaeacce3e0e8eef5f8e9ffa2fffcedefe9">[email protected]</span></a>. Many thanks to Marcel for providing the Globus. I worked on this with CuriousMarc, so check out his <a href="https://www.youtube.com/@CuriousMarc/videos">Globus videos</a>.</p> <h2>Notes and references</h2> <div class="footnote"> <ol> <li id="fn:ink"> <p>In Russian, the name for the device is "袠薪写懈泻邪褌芯褉 袧邪胁懈谐邪褑懈芯薪薪褘泄 袣芯褋屑懈褔械褋泻懈泄" abbreviated as 袠袧袣 (INK). This translates to "space navigation indicator." but I'll use the more descriptive nickname "Globus" (i.e. globe). The Globus has a long history, back to the beginnings of Soviet crewed spaceflight. The first version was simpler and had the Russian acronym 袠袦袩 (IMP). Development of the IMP started in <a href="https://web.mit.edu/slava/space/essays/essay-tiapchenko1.htm">1960</a> for the Vostok (1961) and Voshod (1964) spaceflights. The more complex INK model (described in this blog post) was created for the Soyuz flights, starting in 1967. The landing position feature is the main improvement of the INK model. The Soyuz-TMA (2002) upgraded to the Neptun-ME system which used digital display screens and abandoned the Globus. <a class="footnote-backref" href="#fnref:ink" title="Jump back to footnote 1 in the text">↩</a></p> </li> <li id="fn:day"> <p>According to <a href="https://astronaut.ru/bookcase/article/article152.htm?reload_coolmenus">this document</a>, one revolution of the globe relative to the axis of daily rotation occurs in a time equal to a sidereal day, taking into account the precession of the orbit relative to the earth's axis, caused by the asymmetry of the Earth's gravitational field. (A sidereal day is approximately 4 minutes shorter than a regular 24-hour day. The difference is that the sidereal day is relative to the fixed stars, rather than relative to the Sun.) <a class="footnote-backref" href="#fnref:day" title="Jump back to footnote 2 in the text">↩</a></p> </li> <li id="fn:orbit"> <p>To see how the angle between the poles and the globe's rotation results in the desired orbital inclination, consider two limit cases. First, suppose the angle between is 90°. In this case, the globe is "straight" with the equator horizontal. Rotating the globe along the horizontal axis, flipping the poles end-over-end, will cause the crosshair to trace a polar orbit, giving the expected inclination of 90°. On the other hand, suppose the angle is 0°. In this case, the globe is "sideways" with the equator vertical. Rotating the globe will cause the crosshair to remain over the equator, corresponding to an equatorial orbit with 0° inclination. <a class="footnote-backref" href="#fnref:orbit" title="Jump back to footnote 3 in the text">↩</a></p> </li> <li id="fn:directions"> <p>There is a bit of ambiguity when describing the gear motions. If the end gears are rotating upwards when viewed from the front, the gears are both rotating clockwise when viewed from the right, so I'm referring to them as rotating in the same direction. But if you view each gear from its own side, the gear on the left is turning counterclockwise, so from that perspective they are turning in opposite directions. <a class="footnote-backref" href="#fnref:directions" title="Jump back to footnote 4 in the text">↩</a></p> </li> <li id="fn:torque"> <p>The solenoids are important since they provide all the energy to drive the globe. One of the problems with gear-driven analog computers is that each gear and shaft has a bit of friction and loses a bit of torque, and there is nothing to amplify the signal along the way. Thus, the 27-volt solenoids need to provide enough force to run the entire system. <a class="footnote-backref" href="#fnref:torque" title="Jump back to footnote 5 in the text">↩</a></p> </li> <li id="fn:time"> <p>The orbital time can be adjusted between 86.85 minutes and 96.85 minutes according to <a href="https://astronaut.ru/bookcase/article/article152.htm?reload_coolmenus">this detailed page</a> that describes the Globus in Russian. <a class="footnote-backref" href="#fnref:time" title="Jump back to footnote 6 in the text">↩</a></p> </li> <li id="fn:parameters"> <p>The Globus is manufactured for a particular orbital inclination, in this case 51.8°. The Globus assumes a circular orbit and does not account for any variations. The Globus does not account for any maneuvering in orbit. <a class="footnote-backref" href="#fnref:parameters" title="Jump back to footnote 7 in the text">↩</a></p> </li> <li id="fn:loop"> <p>The outputs from the orbit cam are fed into the overall orbit rotation, which drives the orbit cam. This may seem like an "infinite loop" since the outputs from the cam turn the cam itself. However, the outputs from the cam are a small part of the overall orbit rotation, so the feedback dies off. <a class="footnote-backref" href="#fnref:loop" title="Jump back to footnote 8 in the text">↩</a></p> </li> <li id="fn:scale"> <p>The scales on the light/shadow display are a bit confusing. The inner scale (blue) is measured in percentage of an orbit, up to 100%. The fixed outer scale (red) measures minutes, indicating how many minutes until the spacecraft enters or leaves shadow. The spacecraft completes 100% of an orbit in about 90 minutes, so the scales almost, but not quite, line up. The wheel is driven by the orbit mechanism and turns half a revolution per orbit.</p> <p><a href="https://static.righto.com/images/globus-gearing/light-dark.jpg"><img alt="The light and shadow indicator is controlled by two knobs." class="hilite" height="175" src="https://static.righto.com/images/globus-gearing/light-dark-w500.jpg" title="The light and shadow indicator is controlled by two knobs." width="500" /></a><div class="cite">The light and shadow indicator is controlled by two knobs.</div></p> <p><!-- --> <a class="footnote-backref" href="#fnref:scale" title="Jump back to footnote 9 in the text">↩</a></p> </li> <li id="fn:iss"> <p>The Internation Space Station illustrates how an orbiting spacecraft is illuminated more than 50% of the time due to its height. You can often see the ISS illuminated in the nighttime sky close to sunset and sunrise (<a href="https://spotthestation.nasa.gov/">link</a>). <a class="footnote-backref" href="#fnref:iss" title="Jump back to footnote 10 in the text">↩</a></p> </li> <li id="fn:sinusoid"> <p>The ground track on the map is roughly, but not exactly, sinusoidal. As the orbit swings further from the equator, the track deviates more from a pure sinusoid. The shape will depend, of course, on the rectangular map projection. For more information, see <a href="https://math.stackexchange.com/questions/1843444/how-do-great-circles-project-on-the-mercator-projection">this StackExcahnge post</a>. <a class="footnote-backref" href="#fnref:sinusoid" title="Jump back to footnote 11 in the text">↩</a></p> </li> <li id="fn:formulas"> <p>To get an idea of how the latitude and longitude behave, consider a polar orbit with 90° angle of inclination, one that goes up a line of longitude, crosses the North Pole, and goes down the opposite line of latitude. Now, shift the orbit away from the poles a bit, but keeping a great circle. The spacecraft will go up, nearly along a constant line of longitude, with the latitude increasing steadily. As the spacecraft reaches the peak of its orbit near the North Pole, it will fall a bit short of the Pole but will still rapidly cross over to the other side. During this phase, the spacecraft rapidly crosses many lines of longitude (which are close together near the Pole) until it reaches the opposite line of longitude. Meanwhile, the latitude stops increasing short of 90° and then starts dropping. On the other side, the process repeats, with the longitude nearly constant while the latitude drops relatively constantly.</p> <p>The latitude and longitude are generated by complicated trigonometric functions. The latitude is given by arcsin(sin i * sin (2蟺t/T)), while the longitude is given by 位 = arctan (cos i * tan(2蟺t/T)) + 惟t + 位<sub>0</sub>, where t is the spaceship's flight time starting at the equator, i is the angle of inclination (51.8°), T is the orbital period, 惟 is the angular velocity of the Earth's rotation, and 位<sub>0</sub> is the longitude of the ascending node. <a class="footnote-backref" href="#fnref:formulas" title="Jump back to footnote 12 in the text">↩</a></p> </li> <li id="fn:solenoid"> <p>An important function of the gears is to scale the rotations as needed by using different gear ratios. For the most part, I'm ignoring the gear ratios, but the Earth rotation gearing is interesting. The gear driven by the solenoid has 60 teeth, so it rotates exactly once per minute. This gear drives a shaft with a very small gear on the other end with 15 teeth. This gear meshes with a much larger gear with approximately 75 teeth, which will thus rotate once every 5 minutes. The other end of that shaft has a gear with approximately 15 teeth, meshed with a large gear with approximately 90 teeth. This divides the rate by 6, yielding a rotation every 30 minutes. The sequence of gears and shafts continues, until the rotation is reduced to once per day. (The tooth counts are approximate because the gears are partially obstructed inside the Globus, making counting difficult.) <a class="footnote-backref" href="#fnref:solenoid" title="Jump back to footnote 13 in the text">↩</a></p> </li> <li id="fn:landing"> <p>There's a potential simplification when canceling out the orbital shaft rotation from the Earth rotation. If the orbit motion was taken from differential 5 instead of differential 4, the landing motor effect would get added automatically, eliminating the need for differential 7. I think the landing motor motion was added separately so the mechanism could account for the Earth's rotation during the landing descent. <a class="footnote-backref" href="#fnref:landing" title="Jump back to footnote 14 in the text">↩</a></p> </li> </ol> </div> <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'><span class='post-comment-link'> <a class='comment-link' href='https://www.blogger.com/comment/fullpage/post/6264947694886887540/8868607841305902549' onclick=''> 2 comments: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post/6264947694886887540/8868607841305902549' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=8868607841305902549&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=8868607841305902549&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=8868607841305902549&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=8868607841305902549&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=8868607841305902549&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=8868607841305902549&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/analog' rel='tag'>analog</a>, <a href='http://www.righto.com/search/label/globus' rel='tag'>globus</a>, <a href='http://www.righto.com/search/label/reverse-engineering' rel='tag'>reverse-engineering</a>, <a href='http://www.righto.com/search/label/space' rel='tag'>space</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='https://static.righto.com/images/8086-mul/die-labeled-w600.jpg' itemprop='image_url'/> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='8390323699966089555' itemprop='postId'/> <a name='8390323699966089555'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2023/03/8086-multiplication-microcode.html'>Reverse-engineering the multiplication algorithm in the Intel 8086 processor</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-8390323699966089555' itemprop='description articleBody'> <style> .hilite {cursor:zoom-in} a:link img.hilite, a:visited img.hilite {color: #fff;} a:hover img.hilite {color: #f66;} </style> <style> pre.microcode {font-family: courier, fixed; padding: 10px; background-color: #f5f5f5; display:inline-block;border:none;} pre.microcode span {color: green; font-style:italic; font-family: sans-serif; font-size: 90%;} </style> <p>While programmers today take multiplication for granted, most microprocessors in the 1970s could only add and subtract — multiplication required a slow and tedious loop implemented in assembly code.<span id="fnref:mul"><a class="ref" href="#fn:mul">1</a></span> One of the nice features of the Intel 8086 processor (1978) was that it provided machine instructions for multiplication,<span id="fnref:division"><a class="ref" href="#fn:division">2</a></span> able to multiply 8-bit or 16-bit numbers with a single instruction. Internally, the 8086 still performed a loop, but the loop was implemented in microcode: faster and transparent to the programmer. Even so, multiplication was a slow operation, about 24 to 30 times slower than addition.</p> <p>In this blog post, I explain the multiplication process inside the 8086, analyze the microcode that it used, and discuss the hardware circuitry that helped it out.<span id="fnref:microcode"><a class="ref" href="#fn:microcode">3</a></span> My analysis is based on reverse-engineering the 8086 from die photos. The die photo below shows the chip under a microscope. I've labeled the key functional blocks; the ones that are important to this post are darker. At the left, the ALU (Arithmetic/Logic Unit) performs the arithmetic operations at the heart of multiplication: addition and shifts. Multiplication also uses a few other hardware features: the X register, the F1 flag, and a loop counter. The microcode ROM at the lower right controls the process.</p> <p><a href="https://static.righto.com/images/8086-mul/die-labeled.jpg"><img alt="The 8086 die under a microscope, with main functional blocks labeled. This photo shows the chip with the metal and polysilicon removed, revealing the silicon underneath. Click on this image (or any other) for a larger version." class="hilite" height="592" src="https://static.righto.com/images/8086-mul/die-labeled-w600.jpg" title="The 8086 die under a microscope, with main functional blocks labeled. This photo shows the chip with the metal and polysilicon removed, revealing the silicon underneath. Click on this image (or any other) for a larger version." width="600" /></a><div class="cite">The 8086 die under a microscope, with main functional blocks labeled. This photo shows the chip with the metal and polysilicon removed, revealing the silicon underneath. Click on this image (or any other) for a larger version.</div></p> <h2>Microcode</h2> <p>The multiplication routines in the 8086 are implemented in microcode. Most people think of machine instructions as the basic steps that a computer performs. However, many processors (including the 8086) have another layer of software underneath: microcode. With microcode, instead of building the control circuitry from complex logic gates, the control logic is largely replaced with code. To execute a machine instruction, the computer internally executes several simpler micro-instructions, specified by the microcode. This is especially useful for a machine instruction such as multiplication, which requires many steps in a loop.</p> <!-- The 8086 uses a hybrid approach: although it uses microcode, much of the instruction functionality is implemented with gate logic. This approach removed duplication from the microcode and kept the microcode small enough for 1978 technology. In a sense, the microcode is parameterized. For instance, the microcode can specify a generic Arithmetic/Logic Unit (ALU) operation and a generic register. The gate logic examines the instruction to determine which specific operation to perform and the appropriate register. --> <p>A micro-instruction in the 8086 is encoded into 21 bits as shown below. Every micro-instruction has a move from a source register to a destination register, each specified with 5 bits. The meaning of the remaining bits depends on the type field and can be anything from an ALU operation to a memory read or write to a change of microcode control flow. Thus, an 8086 micro-instruction typically does two things in parallel: the move and the action. For more about 8086 microcode, see my <a href="https://www.righto.com/2022/11/how-8086-processors-microcode-engine.html">microcode blog post</a>.</p> <p><a href="https://static.righto.com/images/8086-mul/microcode-format.jpg"><img alt="The encoding of a micro-instruction into 21 bits. Based on NEC v. Intel: Will Hardware Be Drawn into the Black Hole of Copyright?" class="hilite" height="203" src="https://static.righto.com/images/8086-mul/microcode-format-w700.jpg" title="The encoding of a micro-instruction into 21 bits. Based on NEC v. Intel: Will Hardware Be Drawn into the Black Hole of Copyright?" width="700" /></a><div class="cite">The encoding of a micro-instruction into 21 bits. Based on <a href="https://digitalcommons.law.scu.edu/cgi/viewcontent.cgi?referer=&httpsredir=1&article=1031&context=chtlj">NEC v. Intel: Will Hardware Be Drawn into the Black Hole of Copyright?</a></div></p> <p>The behavior of an ALU micro-operation is important for multiplication. The ALU has three temporary registers that are invisible to the programmer: tmpA, tmpB, and tmpC. An ALU operation takes its first argument from any temporary register, while the second argument always comes from tmpB. An ALU operation requires two micro-instructions. The first micro-instruction specifies the ALU operation and source register, configuring the ALU. For instance, <code>ADD tmpA</code> to add tmpA to the default tmpB. In the next micro-instruction (or a later one), the ALU result can be accessed through the <code>危</code> register and moved to another register.</p> <p>Before I get into the microcode routines, I should explain two ALU operations that play a central role in multiplication: <code>LRCY</code> and <code>RRCY</code>, Left Rotate through Carry and Right Rotate through Carry. (These correspond to the <code>RCL</code> and <code>RCR</code> machine instructions, which rotate through carry left or right.) These operations shift the bits in a 16-bit word, similar to the <code><<</code> and <code>>></code> bit-shift operations in high-level languages, but with an additional feature. Instead of discarding the bit on the end, that bit is moved into the carry flag (<code>CF</code>). Meanwhile, the bit formerly in the carry flag moves into the word. You can think of this as rotating the bits while treating the carry flag as a 17th bit of the word.</p> <p><a href="https://static.righto.com/images/8086-mul/rotates.jpg"><img alt="The left rotate through carry and right rotate through carry micro-instructions." class="hilite" height="172" src="https://static.righto.com/images/8086-mul/rotates-w300.jpg" title="The left rotate through carry and right rotate through carry micro-instructions." width="300" /></a><div class="cite">The left rotate through carry and right rotate through carry micro-instructions.</div></p> <p>These shifts perform an important part of the multiplication process since shifting can be viewed as multiplying by two. <code>LRCY</code> also provides a convenient way to move the most-significant bit to the carry flag, where it can be tested for a conditional jump. (This is important because the top bit is used as the sign bit.) Similarly, <code>RRCY</code> provides access to the least significant bit, very important for the multiplication process. Another important property is that performing <code>RRCY</code> on an upper word and then <code>RRCY</code> on a lower word will perform a 32-bit shift, since the low bit of the upper word will be moved into the high bit of the lower word via the carry bit.</p> <h2>Binary multiplication</h2> <p>The shift-and-add method of multiplication (below) is similar to grade-school long multiplication, except it uses binary instead of decimal. In each row, the multiplicand is multiplied by one digit of the multiplier. (The multiplicand is the value that gets repeatedly added, and the multiplier controls how many times it gets added.) Successive rows are shifted left one digit. At the bottom, the rows are added together to yield the product. The example below shows how 6×5 is calculated in binary using long multiplication.</p> <style type="text/css"> div.mul {font-family: "courier-new", courier, monospace} div.mul .top {border-bottom: 1px solid #ccc;} div.mul .sum {border-top: 1px solid #ccc;} div.mul .dim {color: #aaa;} </style> <div class="mul"> <span> 0110</span> <br/><span class="top"> ×0101</span> <br/><span> 0110</span> <br/><span class="dim"> 0000</span> <br/><span> 0110</span> <br/><span class="dim"> 0000</span> <br/><span class="sum">00011110</span> </div> <p>Binary long multiplication is much simpler than decimal multiplication: at each step, you're multiplying by 0 or 1. Thus, each row is either zero or the multiplicand appropriately shifted (0110 in this case). (Unlike decimal long multiplication, you don't need to know the multiplication table.) This simplifies the hardware implementation, since each step either adds the multiplicand or doesn't. In other words, each step tests a bit of the multiplier, starting with the low bit, to determine if an add should take place or not. This bit can be obtained by shifting the multiplier one bit to the right each step.</p> <p>Although the diagram above shows the sum at the end, a real implementation performs the addition at each step of the loop, keeping a running total. Moreover, in the 8086, instead of shifting the multiplicand to the left during each step, the sum shifts to the right. (The result is the same but it makes the implementation easier.) Thus, multiplying 6×5 goes through the steps below.</p> <div class="mul"> <span> 0101</span> <br/><span class="top"> ×0110</span> <br/><span> 00000</span> <br/><span> 001010</span> <br/><span> 0011110</span> <br/><span> 00011110</span> </div> <p>Why would you shift the result to the right? There's a clever reason for this. Suppose you're multiplying two 16-bit numbers, which yields a 32-bit result. That requires four 16-bit words of storage if you use the straightforward approach. But if you look more closely, the first sum fits into 16 bits, and then you need one more bit at each step. Meanwhile, you're "using up" one bit of the multiplier at each step. So if you squeeze the sum and the multiplier together, you can fit them into two words. Shifting right accomplishes this, as the diagram below illustrates for <code>0xffff</code>×<code>0xf00f</code>. The sum (blue) starts in a 16-bit register called <code>tmpA</code> while the multiplier (green) is stored in the 16-bit <code>tmpB</code> register. In each step, they are both shifted right, so the sum gains one bit and the multiplier loses one bit. By the end, the sum takes up all 32 bits, split across both registers.</p> <style type="text/css"> table.mul {border-collapse: collapse; border: 1px solid #888; font-family: "courier-new", courier, monospace; padding: 2px; font-size:90%;} table.mul th {border-bottom: 1px solid #444;} table.mul th:nth-child(1) {border-left: 1px solid #444; border-right: 2px solid #444;} table.mul th:nth-child(3) {border-left: 1px solid #444;} table.mul th:nth-child(4) {padding: 0 4px;} table.mul tr:nth-child(2) {border-bottom: 1px solid #444;} table.mul tr:nth-child(2) {border-bottom: 1px solid #444;} table.mul td:nth-child(8) {border-right: 1px solid #444;} table.mul td:nth-child(16) {border-right: 2px solid #444;} table.mul td:nth-child(24) {border-right: 1px solid #444;} table.mul td {padding: 0px 4px;} table.mul td.a {background-color: #ddf;} table.mul td.b {background-color: #cfc;} </style> <table class="mul"> <tr style="font-family: sans-serif; color: blue"><th colspan=16>sum (tmpA)</th><th colspan=16 style="font-family:sans-serif; color: green">multiplier (tmpC)</th></tr> <tr><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="b">1</td><td class="b">1</td><td class="b">1</td><td class="b">1</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">1</td><td class="b">1</td><td class="b">1</td><td class="b">1</td></tr> <tr><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="b">1</td><td class="b">1</td><td class="b">1</td><td class="b">1</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">1</td><td class="b">1</td><td class="b">1</td></tr> <tr><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="b">1</td><td class="b">1</td><td class="b">1</td><td class="b">1</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">1</td><td class="b">1</td></tr> <tr><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="b">1</td><td class="b">1</td><td class="b">1</td><td class="b">1</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">1</td></tr> <tr><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="b">1</td><td class="b">1</td><td class="b">1</td><td class="b">1</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td></tr> <tr><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="b">1</td><td class="b">1</td><td class="b">1</td><td class="b">1</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td></tr> <tr><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="b">1</td><td class="b">1</td><td class="b">1</td><td class="b">1</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td></tr> <tr><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="b">1</td><td class="b">1</td><td class="b">1</td><td class="b">1</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td></tr> <tr><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="b">1</td><td class="b">1</td><td class="b">1</td><td class="b">1</td><td class="b">0</td><td class="b">0</td><td class="b">0</td><td class="b">0</td></tr> <tr><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="b">1</td><td class="b">1</td><td class="b">1</td><td class="b">1</td><td class="b">0</td><td class="b">0</td><td class="b">0</td></tr> <tr><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="b">1</td><td class="b">1</td><td class="b">1</td><td class="b">1</td><td class="b">0</td><td class="b">0</td></tr> <tr><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="b">1</td><td class="b">1</td><td class="b">1</td><td class="b">1</td><td class="b">0</td></tr> <tr><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="b">1</td><td class="b">1</td><td class="b">1</td><td class="b">1</td></tr> <tr><td class="a">1</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="b">1</td><td class="b">1</td><td class="b">1</td></tr> <tr><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="b">1</td><td class="b">1</td></tr> <tr><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="b">1</td></tr> <tr><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">1</td></tr> </table> <h2>The multiplication microcode</h2> <p>The 8086 has four multiply instructions to handle signed and unsigned multiplication of byte and word operands. These machine instructions are implemented in microcode. I'll start by describing the unsigned word multiplication, which multiplies two 16-bit values and produces a 32-bit result. The source word is provided by either a register or memory. It is multiplied by <code>AX</code>, the accumulator register. The 32-bit result is returned in the <code>DX</code> and <code>AX</code> registers.</p> <p>The microcode below is the main routine for word multiplication, both signed and unsigned. Each micro-instruction specifies a register move on the left, and an action on the right. The moves transfer words between the visible registers and the ALU's temporary registers, while the actions are mostly subroutine calls to other micro-routines.</p> <pre class="microcode"> move action AX → tmpC LRCY tmpC <span><b>iMUL rmw:</b></span> M → tmpB CALL X0 PREIMUL <span>called for signed multiplication</span> CALL CORX <span>the core routine</span> CALL F1 NEGATE <span>called for negative result</span> CALL X0 IMULCOF <span>called for signed multiplication</span> tmpC → AX JMPS X0 7 CALL MULCOF <span>called for unsigned multiplication</span> tmpA → DX RNI </pre> <p>The microcode starts by moving one argument <code>AX</code> into the ALU's temporary C register and setting up the ALU to perform a Left Rotate through Carry on this register, in order to access the sign bit. Next, it moves the second argument <code>M</code> into the temporary B register; <code>M</code> references the register or memory specified in the second byte of the instruction, the "ModR/M" byte. For a signed multiply instruction, the <code>PREIMUL</code> micro-subroutine is called, but I'll skip that for now. (The <code>X0</code> condition tests bit 3 of the instruction, which in this case distinguishes <code>MUL</code> from <code>IMUL</code>.) Next, the <code>CORX</code> subroutine is called, which is the heart of the multiplication.<span id="fnref:corx"><a class="ref" href="#fn:corx">4</a></span> If the result needs to be negated (indicated by the <code>F1</code> condition), the <code>NEGATE</code> micro-subroutine is called. For signed multiplication, <code>IMULCOF</code> is then called to set the carry and overflow flags, while <code>MULCOF</code> is called for unsigned multiplication. Meanwhile, the result bytes are moved from the temporary C and temporary registers to the <code>AX</code> and <code>DX</code> registers. Finally, <code>RNI</code> runs the next machine instruction, ending the microcode routine.</p> <h3><code>CORX</code></h3> <p>The heart of the multiplication code is the <code>CORX</code> routine, which performs the multiplication loop, computing the product through shifts and adds. The first two lines set up the loop, initializing the sum (tmpA) to 0. The number of loops is controlled by a special-purpose loop counter. The <code>MAXC</code> micro-instruction initializes the counter to 7 or 15, for a byte or word multiply respectively. The first shift of tmpC is performed, putting the low bit into the carry flag.</p> <p>The loop body performs the shift-and-add step. It tests the carry flag, the low bit of the multiplicand. It skips over the <code>ADD</code> if there is no carry (<code>NCY</code>). Otherwise, tmpB is added to tmpA. (As tmpA gets shifted to the right, tmpB gets added to higher and higher positions in the result.) The tmpA and tmpC registers are rotated right. This also puts the next bit of the multiplicand into the carry flag for the next cycle. The microcode jumps to the top of the loop if the counter is not zero (<code>NCZ</code>). Otherwise, the subroutine returns with the result in tmpA and tmpC.</p> <pre class="microcode"> ZERO → tmpA RRCY tmpC <span><b>CORX:</b> initialize right rotate</span> 危 → tmpC MAXC <span> get rotate result, initialize counter to max value</span> JMPS NCY 8 <span><b>5:</b> top of loop</span> ADD tmpA <span>conditionally add</span> 危 → tmpA F <span>sum to tmpA, update flags to get carry</span> RRCY tmpA <span><b>8:</b> 32-bit shift of tmpA/tmpC</span> 危 → tmpA RRCY tmpC 危 → tmpC JMPS NCZ 5 <span>loop to 5 if counter is not 0</span> RTN </pre> <h3><code>MULCOF</code></h3> <p>The last subroutine is <code>MULCOF</code>, which configures the carry and overflow flags. The 8086 uses the rule that if the upper half of the result is nonzero, the carry and overflow flags are set, otherwise they are cleared. The first two lines pass tmpA (the upper half of the result) through the ALU to set the zero flag for the conditional jump. As a side-effect, the other status flags will get set but these values are "undefined" in the documentation.<span id="fnref:flags"><a class="ref" href="#fn:flags">6</a></span> If the test is nonzero, the carry and overflow flags are set (<code>SCOF</code>), otherwise they are cleared (<code>CCOF</code>).<span id="fnref:overflow"><a class="ref" href="#fn:overflow">5</a></span> The <code>SCOF</code> and <code>CCOF</code> micro-operations were implemented solely for used by multiplication, illustrating how microcode can be designed around specific needs.</p> <pre class="microcode"> PASS tmpA <span><b>MULCOF:</b> pass tmpA through to test if zero</span> 危 → no dest JMPS 12 F <span>update flags</span> JMPS Z 8 <span><b>12:</b> jump if zero</span> SCOF RTN <span>otherwise set carry and overflow</span> CCOF RTN <span><b>8:</b> clear carry and overflow</span> </pre> <h2>8-bit multiplication</h2> <p>The 8086 has separate instructions for 8-bit multiplication. The process for 8-bit multiplication is similar to 16-bit multiplication, except the values are half as long and the shift-and-add loop executes 8 times instead of 16. As shown below, the 8-bit sum starts in the low half of the temporary A register and is shifted left into tmpC. Meanwhile, the 8-bit multiplier starts in the low half of tmpC and is shifted out to the right. At the end, the result is split between tmpA and tmpC.</p> <table class="mul"> <tr style="font-family: sans-serif; color: blue"><th colspan=16>sum (tmpA)</th><th colspan=16 style="font-family:sans-serif; color: green">multiplier (tmpC)</th></tr> <tr><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td class="a">0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td class="b">0</td><td class="b">1</td><td class="b">0</td><td class="b">1</td><td class="b">0</td><td class="b">1</td><td class="b">0</td><td class="b">1</td></tr> <tr><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td class="b">0</td><td class="b">1</td><td class="b">0</td><td class="b">1</td><td class="b">0</td><td class="b">1</td><td class="b">0</td></tr> <tr><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td class="b">0</td><td class="b">1</td><td class="b">0</td><td class="b">1</td><td class="b">0</td><td class="b">1</td></tr> <tr><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td class="a">1</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td class="b">0</td><td class="b">1</td><td class="b">0</td><td class="b">1</td><td class="b">0</td></tr> <tr><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td class="a">0</td><td class="a">1</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td class="b">0</td><td class="b">1</td><td class="b">0</td><td class="b">1</td></tr> <tr><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td class="b">0</td><td class="b">1</td><td class="b">0</td></tr> <tr><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td class="a">0</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td class="b">0</td><td class="b">1</td></tr> <tr><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td class="b">0</td></tr> <tr><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td class="a">0</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">0</td><td class="a">0</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">0</td><td class="a">1</td><td class="a">1</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td></tr> </table> <p>The 8086 supports many instructions with byte and word versions, using 8-bit or 16-bit arguments. In most cases, the byte and word instructions use the same microcode, with the ALU and register hardware using bytes or words based on the instruction. However, the byte- and word-multiply instructions use different registers, requiring microcode changes. In particular, the multiplier is in <code>AL</code>, the low half of the accumulator. At the end, the 16-bit result is returned in <code>AX</code>, the full 16-bit accumulator; two micro-instructions assemble the result from tmpC and tmpA into the two bytes of the accumulator, 'AL' and 'AH' respectively. Apart from those changes, the microcode is the same as the word multiply microcode discussed earlier.</p> <pre class="microcode"> AL → tmpC LRCY tmpC <span><b>iMUL rmb:</b></span> M → tmpB CALL X0 PREIMUL CALL CORX CALL F1 NEGATE CALL X0 IMULCOF tmpC → AL JMPS X0 7 CALL MULCOF tmpA → AH RNI </pre> <h2>Signed multiplication</h2> <p>The 8086 (like most computers) represents signed numbers using a format called two's complement. While a regular byte holds a number from 0 to 255, a signed byte holds a number from -128 to 127. A negative number is formed by flipping all the bits (known as the one's complement) and then adding 1, yielding the two's complement value.<span id="fnref:complement"><a class="ref" href="#fn:complement">7</a></span> For instance, +5 is <code>0x05</code> while -5 is <code>0xfb</code>. (Note that the top bit of a number is set for a negative number; this is the sign bit.) The nice thing about two's complement numbers is that the same addition and subtraction operations work on both signed and unsigned values. Unfortunately, this is not the case for signed multiplication, since signed and unsigned values yield different results due to sign extension.</p> <p>The 8086 has separate multiplication instructions <code>IMUL</code> (Integer Multiply) to perform signed multiplication. The 8086 performs signed multiplication by converting the arguments to positive values, performing unsigned multiplication, and then negating the result if necessary. As shown above, signed and unsigned multiplication both use the same microcode, but the microcode conditionally calls some subroutines for signed multiplication. I will discuss those micro-subroutines below.</p> <h3><code>PREIMUL</code></h3> <p>The first subroutine for signed multiplication is <code>PREIMUL</code>, performing preliminary operations for integer multiplication. It converts the two arguments, stored in tmpC and tmpB, to positive values. It keeps track of the signs using an internal flag called <code>F1</code>, toggling this flag for a negative argument. This conveniently handles the rule that two negatives make a positive since complementing the <code>F1</code> flag twice will clear it.</p> <p>This microcode, below, illustrates the complexity of microcode and how micro-operations are carefully arranged to get the right values at the right time. The first micro-instruction performs one ALU operation and sets up a second operation. The calling code had set up the ALU to perform <code>LRCY tmpC</code>, so that's the result returned by 危 (and discarded). Performing a left rotate and discarding the result may seem pointless, but the important side-effect is that the top bit (i.e. the sign bit) ends up in the carry flag. The microcode does not have a conditional jump based on the sign, but has a conditional jump based on carry, so the point is to test if tmpC is negative. The first micro-instruction also sets up negation (<code>NEG tmpC</code>) for the <em>next</em> ALU operation.</p> <pre class="microcode"> 危 → no dest NEG tmpC <span><b>PREIMUL:</b> set up negation of tmpC</span> JMPS NCY 7 <span>jump if tmpC positive</span> 危 → tmpC CF1 <span>if negative, negate tmpC, flip F1</span> JMPS 7 <span>jump to shared code</span> LRCY tmpB <span><b>7:</b></span> 危 → no dest NEG tmpB <span>set up negation of tmpB</span> JMPS NCY 11 <span>jump if tmpB positive</span> 危 → tmpB CF1 RTN <span>if negative, negate tmpB, flip F1</span> RTN <span><b>11:</b> return</span> </pre> <p>For the remaining lines, if the carry is clear (<code>NCY</code>), the next two lines are skipped. Otherwise, the ALU result (<code>危</code>) is written to tmpC, making it positive, and the <code>F1</code> flag is complemented with <code>CF1</code>. (The second short jump (<code>JMPS</code>) may look unnecessary, but I reordered the code for clarity.) The second half of the microcode performs a similar test on tmpB. If tmpB is negative, it is negated and <code>F1</code> is toggled.</p> <h3><code>NEGATE</code></h3> <p>The microcode below is called after computing the result, if the result needs to be made negative. Negation is harder than you might expect because the result is split between the tmpA and tmpC registers. The two's complement operation (<code>NEG</code>) is applied to the low word, while either 2's complement or one's complement (<code>COM1</code>) is applied to the upper word, depending on the carry for mathematical reasons.<span id="fnref:neg"><a class="ref" href="#fn:neg">8</a></span> The code also toggles F1 and makes tmpB positive; I think this code is only useful for division, which also uses the <code>NEGATE</code> subroutine.</p> <pre class="microcode"> NEG tmpC <span><b>NEGATE:</b> negate tmpC</span> 危 → tmpC COM1 tmpA F <span>maybe complement tmpA</span> JMPS CY 6 NEG tmpA <span>negate tmpA if there's no carry</span> 危 → tmpA CF1 <span><b>6:</b> toggle F1 for some reason</span> LRCY tmpB <span><b>7:</b> test sign of tmpB</span> 危 → no dest NEG tmpB <span>maybe negate tmpB</span> JMPS NCY 11 <span>skip if tmpB positive</span> 危 → tmpB CF1 RTN <span>else negate tmpB, toggle F1</span> RTN <span><b>11:</b> return</span> </pre> <h3><code>IMULCOF</code></h3> <p>The <code>IMULCOF</code> routine is similar to <code>MULCOF</code>, but the calculation is a bit trickier for a signed result. This routine sets the carry and overflow flags if the upper half of the result is significant, that is, it is not just the sign extension of the lower half.<span id="fnref:imulcof"><a class="ref" href="#fn:imulcof">9</a></span> In other words, the top byte is not significant if it duplicates the top bit (the sign bit) of the lower byte. The trick in the microcode is to add the top bit of the lower byte to the upper byte by putting it in the carry flag and performing an add with carry (<code>ADC</code>) of 0. If the result is 0, the upper byte is not significant, handling the positive and negative cases. (This also holds for words instead of bytes.)</p> <pre class="microcode"> ZERO → tmpB LRCY tmpC <span><b>IMULCOF:</b> get top bit of tmpC</span> 危 → no dest ADC tmpA <span>add to tmpA and 0 (tmpB)</span> 危 → no dest F <span>update flags</span> JMPS Z 8 <span><b>12: jump if zero result</b></span> SCOF RTN <span>otherwise set carry and overflow</span> CCOF RTN <span><b>8:</b> clear carry and overflow</span> </pre> <h2>The hardware for multiplication</h2> <p>For the most part, the 8086 uses the regular ALU addition and shifts for the multiplication algorithm. Some special hardware features provide assistance.</p> <h3>Loop counter</h3> <p>The 8086 has a special 4-bit loop counter for multiplication. This counter starts at 7 for byte multiplication and 15 for word multiplication, based on the instruction. This loop counter allows the microcode to decrement the counter, test for the end, and perform a conditional branch in one micro-operation. The counter is implemented with four flip-flops, along with logic to compute the value after decrementing by one. The <code>MAXC</code> (Maximum Count) micro-instruction sets the counter to 7 or 15 for byte or word operations respectively. The <code>NCZ</code> (Not Counter Zero) micro-instruction has two actions. First, it performs a conditional jump if the counter is nonzero. Second, it decrements the counter.</p> <h3>X register</h3> <p>The multiplication microcode uses an internal register called the <code>X</code> register to distinguish between the <code>MUL</code> and <code>IMUL</code> instructions. The <code>X</code> register is a 3-bit register that holds the ALU opcode, indicated by bits 5–3 of the instruction.<span id="fnref:x-reg"><a class="ref" href="#fn:x-reg">10</a></span> Since the instruction is held in the Instruction Register, you might wonder why a separate register is required. The motivation is that some opcodes specify the type of ALU operation in the second byte of the instruction, the ModR/M byte, bits 5–3.<span id="fnref:opcode"><a class="ref" href="#fn:opcode">11</a></span> Since the ALU operation is sometimes specified in the first byte and sometimes in the second byte, the <code>X</code> register was added to handle both these cases.</p> <p>For the most part, the <code>X</code> register indicates which of the eight standard ALU operations is selected (<code>ADD</code>, <code>OR</code>, <code>ADC</code>, <code>SBB</code>, <code>AND</code>, <code>SUB</code>, <code>XOR</code>, <code>CMP</code>). However, a few instructions use bit 0 of the <code>X</code> register to distinguish between other pairs of instructions. For instance, it distinguishes between <code>MUL</code> and <code>IMUL</code>, <code>DIV</code> and <code>IDIV</code>, <code>CMPS</code> and <code>SCAS</code>, <code>MOVS</code> and <code>LODS</code>, or <code>AAA</code> and <code>AAS</code>. While these instruction pairs may appear to have arbitrary opcodes, they have been carefully assigned. The microcode can test this bit using the <code>X0</code> condition and perform conditional jumps.</p> <p>The implementation of the <code>X</code> register is straightforward, consisting of three flip-flops to hold the three bits of the instruction. The flip-flops are loaded from the prefetch queue bus during First Clock and during Second Clock for appropriate instructions, as the instruction bytes travel over the bus. Testing bit 0 of the <code>X</code> register with the <code>X0</code> condition is supported by the microcode condition evaluation circuitry, so it can be used for conditional jumps in the microcode.</p> <h3>The F1 flag</h3> <p>The multiplication microcode uses an internal flag called <code>F1</code>,<span id="fnref:f1"><a class="ref" href="#fn:f1">12</a></span> which has two distinct uses. The flag keeps track of a <code>REP</code> prefix for use with a string operation. But the <code>F1</code> flag is also used by signed multiplication and division to keep track of the sign. The <code>F1</code> flag can be toggled by microcode through the <code>CF1</code> (Complement F1) micro-instruction. The <code>F1</code> flag is implemented with a flip-flop, along with a multiplexer to select the value. It is cleared when a new instruction starts, set by a <code>REP</code> prefix, and toggled by the <code>CF1</code> micro-instruction.</p> <p>The diagram below shows how the F1 latch and the loop counter appear on the die. In this image, the metal layer has been removed, showing the silicon and the polysilicon wiring underneath.</p> <p><a href="https://static.righto.com/images/8086-mul/counter.jpg"><img alt="The counter and F1 latch as they appear on the die. The latch for the REP state is also here." class="hilite" height="308" src="https://static.righto.com/images/8086-mul/counter-w600.jpg" title="The counter and F1 latch as they appear on the die. The latch for the REP state is also here." width="600" /></a><div class="cite">The counter and F1 latch as they appear on the die. The latch for the REP state is also here.</div></p> <h2>Later advances in multiplication</h2> <p>The 8086 was pretty slow at multiplying compared to later Intel processors.<span id="fnref:performance"><a class="ref" href="#fn:performance">13</a></span> The 8086 took up to 133 clock cycles to multiply unsigned 16-bit values due to the complicated microcode loops. By 1982, the Intel 286 processor cut this time down to 21 clock cycles. The Intel 486 (1989) used an improved algorithm that could end early, so multiplying by a small number could take just 9 cycles.</p> <p>Although these optimizations improved performance, they still depended on looping over the bits. With the shift to 32-bit processors, the loop time became unwieldy. The solution was to replace the loop with hardware: instead of performing 32 shift-and-add loops, an array of adders could compute the multiplication in one step. This quantity of hardware was unreasonable in the 8086 era, but as Moore's law made transistors smaller and cheaper, hardware multiplication became practical. For instance, the Cyrix Cx486SLC (1992) had a 16-bit hardware multiplier that cut word multiply down to 3 cycles. The Intel Core 2 (2006) was even faster, able to complete a 32-bit multiplication every clock cycle.</p> <!-- Manual page 26-160 http://www.bitsavers.org/components/intel/80486/i486_Processor_Programmers_Reference_Manual_1990.pdf --> <!-- https://techmonitor.ai/technology/cyrix_promises_misery_for_intel_with_its_cx486slc --> <!-- Pentium: alpert 1993 --> <p>Hardware multiplication is a fairly complicated subject, with many optimizations to maximize performance while minimizing hardware.<span id="fnref:hardware"><a class="ref" href="#fn:hardware">14</a></span> Simply replacing the loop with a sequence of 32 adders is too slow because the result would be delayed while propagating through all the adders. The solution is to arrange the adders as a tree to provide parallelism. The first layer has 16 adders to add pairs of terms. The next layer adds pairs of these partial sums, and so forth. The resulting tree of adders is 5 layers deep rather than 32, reducing the time to compute the sum. Real multipliers achieve further performance improvements by splitting up the adders and creating a more complex tree: the venerable <a href="https://en.wikipedia.org/wiki/Wallace_tree">Wallace tree</a> (1964) and <a href="https://en.wikipedia.org/wiki/Dadda_multiplier">Dadda multiplier</a> (1965) are two popular approaches. Another optimization is the <a href="https://en.wikipedia.org/wiki/Booth%27s_multiplication_algorithm">Booth algorithm</a> (1951), which performs signed multiplication directly, without converting the arguments to positive values first. The Pentium 4 (2000) used a Booth encoder and a Wallace tree (<a href="https://past.date-conference.com/proceedings-archive/2017/pyear/PAPERS/2002/DATE02/PDFFILES/01B_1.PDF">ref</a>), but research in the early 2000s found the Dadda tree is faster and it is now more popular.</p> <h2>Conclusions</h2> <p>Multiplication is much harder to compute than addition or subtraction. The 8086 processor hid this complexity from the programmer by providing four multiplication instructions for byte and word multiplication of signed or unsigned values. These instructions implemented multiplication in microcode, performing shifts and adds in a loop. By using microcode subroutines and conditional execution, these four machine instructions share most of the microcode. As the microcode capacity of the 8086 was very small, this was a critical feature of the implementation.</p> <p>If you made it through all the discussion of microcode, congratulations! Microcode is even harder to understand than assembly code. Part of the problem is that microcode is very fine-grain, with even ALU operations split into multiple steps. Another complication is that 8086 microcode performs a register move and another operation in parallel, so it's hard to keep track of what's going on. Microcode can seem a bit like a jigsaw puzzle, with pieces carefully fit together as compactly as possible. I hope the explanations here made sense, or at least gave you a feel for how microcode operates.</p> <p>I've written multiple <a href="https://www.righto.com/search/label/8086">posts on the 8086</a> so far and plan to continue reverse-engineering the 8086 die so follow me on Twitter <a href="https://twitter.com/kenshirriff">@kenshirriff</a> or <a href="http://www.righto.com/feeds/posts/default">RSS</a> for updates. I've also started experimenting with Mastodon recently as <a href="https://oldbytes.space/@kenshirriff">@<span class="__cf_email__" data-cfemail="8fe4eae1fce7e6fdfde6e9e9cfe0e3ebedf6fbeafca1fcffeeecea">[email protected]</span></a>.</p> <h2>Notes and references</h2> <div class="footnote"> <ol> <li id="fn:mul"> <p>Mainframes going back to ENIAC had multiply and divide instructions. However, early microprocessors took a step back and didn't supports these more complex operations. (My theory is that the decline in memory prices made it more cost-effective to implement multiply and divide in software than hardware.) The National Semiconductor <a href="https://en.wikipedia.org/wiki/IMP-16">IMP-16</a>, a 16-bit bit-slice microprocessor from 1973, may be the first with multiply and divide instructions. The 8-bit <a href="https://en.wikipedia.org/wiki/Motorola_6809">Motorola 6809</a> processor (1978) included 8-bit multiplication but not division. I think the 8086 was the first Intel processor to support multiplication. <a class="footnote-backref" href="#fnref:mul" title="Jump back to footnote 1 in the text">↩</a></p> </li> <li id="fn:division"> <p>The 8086 also supported division. Although the division instructions are similar to multiplication in many ways, I'm focusing on multiplication and ignoring division for this blog post. <a class="footnote-backref" href="#fnref:division" title="Jump back to footnote 2 in the text">↩</a></p> </li> <li id="fn:microcode"> <p>My microcode analysis is based on Andrew Jenner's <a href="https://www.reenigne.org/blog/8086-microcode-disassembled/">8086 microcode disassembly</a>. <a class="footnote-backref" href="#fnref:microcode" title="Jump back to footnote 3 in the text">↩</a></p> </li> <li id="fn:corx"> <p>I think <code>CORX</code> stands for <code>Core Multiply</code> and <code>CORD</code> stands for <code>Core Divide</code>. <a class="footnote-backref" href="#fnref:corx" title="Jump back to footnote 4 in the text">↩</a></p> </li> <li id="fn:overflow"> <p>The definitions of carry and overflow are different for multiplication compared to addition and subtraction. Note that the result of a multiplication operation will always fit in the available result space, which is twice as large as the arguments. For instance, the biggest value you can get by multiplying 16-bit values is <code>0xffff</code>×<code>0xffff</code>=<code>0xfffe0001</code> which fits into 32 bits. (Signed and 8-bit multiplications fit similarly.) This is in contrast to addition and subtraction, which can exceed their available space. A carry indicates that an addition exceeded its space when treated as unsigned, while an overflow indicates that an addition exceeded its space when treated as unsigned. <a class="footnote-backref" href="#fnref:overflow" title="Jump back to footnote 5 in the text">↩</a></p> </li> <li id="fn:flags"> <p>The Intel documentation states that the sign, carry, overflow, and parity flags are undefined after the <code>MUL</code> operation, even though the microcode causes them to be computed. The meaning of "undefined" is that programmers shouldn't count on the flag values because Intel might change the behavior in later chips. <a href="https://www.vogons.org/viewtopic.php?t=46211">This thread</a> discusses the effects of <code>MUL</code> on the flags, and how the behavior is different on the <a href="https://en.wikipedia.org/wiki/NEC_V20">NEC V20</a> chip. <a class="footnote-backref" href="#fnref:flags" title="Jump back to footnote 6 in the text">↩</a></p> </li> <li id="fn:complement"> <p>It may be worth explaining why the two's complement of a number is defined by adding 1 to the one's complement. The one's complement of a number simply flips all the bits. If you take a byte value <code>n</code>, <code>0xff</code> - <code>n</code> is the one's complement, since a 1 bit in <code>n</code> produces a 0 bit in the result.</p> <p>Now, suppose we want to represent -5 as a signed byte. Adding <code>0x100</code> will keep the same byte value with a carry out of the byte. But <code>0x100</code> - 5 = (1 + 0xff) - 5 = 1 + (<code>0xff</code> - 5) = 1 + (one's complement of 5). Thus, it makes sense mathematically to represent -5 by adding 1 to the one's complement of 5, and this holds for any value. <a class="footnote-backref" href="#fnref:complement" title="Jump back to footnote 7 in the text">↩</a></p> </li> <li id="fn:neg"> <p>The negation code is a bit tricky because the result is split across two words. In most cases, the upper word is bitwise complemented. However, if the lower word is zero, then the upper word is negated (two's complement). I'll demonstrate with 16-bit values to keep the examples small. The number 257 (0x0101) is negated to form -257 (0xfeff). Note that the upper byte is the one's complement (0x01 vs 0xfe) while the lower byte is two's complement (0x01 vs 0xff). On the other hand, the number 256 (0x0100) is negated to form -256 (0xff00). In this case, the upper byte is the two's complement (0x01 vs 0xff) and the lower byte is also the two's complement (0x00 vs 0x00).</p> <p>(Mathematical explanation: the two's complement is formed by taking the one's complement and adding 1. In most cases, there won't be a carry from the low byte to the upper byte, so the upper byte will remain the one's complement. However, if the low byte is 0, the complement is 0xff and adding 1 will form a carry. Adding this carry to the upper byte yields the two's complement of that byte.)</p> <p>To support multi-word negation, the 8086's <code>NEG</code> instruction clears the carry flag if the operand is 0, and otherwise sets the carry flag. (This is the opposite from the above because subtractions (including <code>NEG</code>) treat the carry flag as a borrow flag, with the opposite meaning.) The microcode <code>NEG</code> operation has identical behavior to the machine instruction, since it is used to implement the machine instruction.</p> <p>Thus to perform a two-word negation, the microcode negates the low word (tmpC) and updates the flags (<code>F</code>). If the carry is set, the one's complement is applied to the upper word (tmpA). But if the carry is cleared, the two's complement is applied to tmpA. <a class="footnote-backref" href="#fnref:neg" title="Jump back to footnote 8 in the text">↩</a></p> </li> <li id="fn:imulcof"> <p>The <code>IMULCOF</code> routine considers the upper half of the result significant if it is not the sign extension of the lower half. For instance, dropping the top byte of <code>0x0005</code> (+5) yields 0x05 (+5). Dropping the top byte of <code>0xfffb</code> (-5) yields 0xfb (-5). Thus, the upper byte is not significant in these cases. Conversely, dropping the top byte of <code>0x00fb</code> (+251) yields <code>0xfb</code> (-5), so the upper byte is significant. <a class="footnote-backref" href="#fnref:imulcof" title="Jump back to footnote 9 in the text">↩</a></p> </li> <li id="fn:x-reg"> <p>Curiously, the <a href="https://patents.google.com/patent/US4449184A/">8086 patent</a> states that the <code>X</code> register is a 4-bit register holding bits 3–6 of the byte (col. 9, line 20). But looking at the die, it is a 3-bit register holding bits 3–5 of the byte. <a class="footnote-backref" href="#fnref:x-reg" title="Jump back to footnote 10 in the text">↩</a></p> </li> <li id="fn:opcode"> <p>Some instructions are specified by bits 5–3 in the ModR/M byte rather than in the first opcode byte. The motivation is to avoid wasting bits for instructions that use a ModR/M byte but don't need a register specification. For instance, consider the instruction <code>ADD [BX],0x1234</code>. This instruction uses a ModR/M byte to specify the memory address. However, because it uses an immediate operand, it does not need the register specification normally provided by bits 5–3 of the ModR/M byte. This frees up the bits to specify the instruction. From one perspective, this is an ugly hack, while from another perspective it is a clever optimization. <a class="footnote-backref" href="#fnref:opcode" title="Jump back to footnote 11 in the text">↩</a></p> </li> <li id="fn:f1"> <p>Andrew Jenner discusses the F1 flag and the interaction between <code>REP</code> and multiplication <a href="https://www.reenigne.org/blog/8086-microcode-disassembled/">here</a>. <a class="footnote-backref" href="#fnref:f1" title="Jump back to footnote 12 in the text">↩</a></p> </li> <li id="fn:performance"> <p>Here are some detailed performance numbers. The 8086 processor takes 70–77 clock cycles to multiply 8-bit values and 118–133 clock cycles to multiply 16-bit values. Signed multiplies are a bit slower because of the sign calculations: 80–98 and 128–154 clock cycles respectively. The time is variable because of the conditional jumps in the multiplication process.</p> <p>The Intel 186 (1982) optimized multiplication slightly, bringing the register word multiply down to 35–37 cycles. The Intel 286 (also 1982) reduced this to 21 clocks. The 486 (1989) used a shift-add multiply function but it had an "early out" algorithm that stopped when the remaining bits were zero, so a 16-bit multiply could take from 9 to 22 clocks. The 8087 floating point coprocessor (1980) used radix-4 multiplication, multiplying by pairs of bits at a time and either adding or subtracting. This yields half the addition cycles. The Pentium's P5 micro-architecture (1993) took the unusual approach of reusing the floating-point unit's hardware multiplier for integer multiplication, taking 10 cycles for a 32-bit multiplication. <a class="footnote-backref" href="#fnref:performance" title="Jump back to footnote 13 in the text">↩</a></p> </li> <li id="fn:hardware"> <p><a href="https://inst.eecs.berkeley.edu/~eecs151/sp18/files/Lecture21.pdf">This presentation</a> gives a good overview of implementations of multiplication in hardware. <a class="footnote-backref" href="#fnref:hardware" title="Jump back to footnote 14 in the text">↩</a></p> </li> </ol> </div> <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'><span class='post-comment-link'> <a class='comment-link' href='https://www.blogger.com/comment/fullpage/post/6264947694886887540/8390323699966089555' onclick=''> 13 comments: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post/6264947694886887540/8390323699966089555' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=8390323699966089555&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=8390323699966089555&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=8390323699966089555&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=8390323699966089555&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=8390323699966089555&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=8390323699966089555&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/8086' rel='tag'>8086</a>, <a href='http://www.righto.com/search/label/chips' rel='tag'>chips</a>, <a href='http://www.righto.com/search/label/microcode' rel='tag'>microcode</a>, <a href='http://www.righto.com/search/label/reverse-engineering' rel='tag'>reverse-engineering</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> </div> <div class='blog-pager' id='blog-pager'> <span id='blog-pager-newer-link'> <a class='blog-pager-newer-link' href='http://www.righto.com/search?updated-max=2023-08-12T09:26:00-07:00&max-results=7&reverse-paginate=true' id='Blog1_blog-pager-newer-link' title='Newer Posts'>Newer Posts</a> </span> <span id='blog-pager-older-link'> <a class='blog-pager-older-link' href='http://www.righto.com/search?updated-max=2023-03-15T08:53:00-07:00&max-results=7' id='Blog1_blog-pager-older-link' title='Older Posts'>Older Posts</a> </span> <a class='home-link' href='http://www.righto.com/'>Home</a> </div> <div class='clear'></div> </div></div> </div> </div> <div class='column-left-outer'> <div class='column-left-inner'> <aside> </aside> </div> </div> <div class='column-right-outer'> <div class='column-right-inner'> <aside> <div class='sidebar section' id='sidebar-right-1'><div class='widget HTML' data-version='1' id='HTML2'> <div class='widget-content'> <style> @import url('https://fonts.googleapis.com/css?family=Montserrat:300,400,500,700'); .form-preview { display: flex; flex-direction: column; justify-content: center; margin-top: 30px; padding: clamp(17px, 5%, 40px) clamp(17px, 7%, 50px); max-width: 350px; min-height: 200px; border-radius: 6px; box-shadow: 0 5px 25px rgba(34, 60, 47, 0.25); } .form-preview, .form-preview *{ box-sizing: border-box; } .form-preview .preview-heading { width: 100%; } .form-preview .preview-heading h5{ margin-top: 0; margin-bottom: 0; } .form-preview .preview-input-field { margin-top: 20px; width: 100%; } .form-preview .preview-input-field input { width: 100%; height: 40px; border-radius: 6px; border: 2px solid #e9e8e8; background-color: #fff; outline: none; } .form-preview .preview-input-field input::placeholder, .form-preview .preview-input-field input { opacity: 0.5; color: #000; font-family: "Montserrat"; font-size: 14px; font-weight: 500; line-height: 20px; text-align: center; } .form-preview .preview-submit-button { margin-top: 10px; width: 100%; } .form-preview .preview-submit-button button { width: 100%; height: 40px; border: 0; border-radius: 6px; line-height: 0px; } .form-preview .preview-submit-button button:hover { cursor: pointer; } </style><form data-v-4c58e686="" action="https://api.follow.it/subscription-form/U3NBTmZKVkI1YVpCa000a0RCZHFiQ3FYMko1cWRTZTN6K3hJdWM2QWxJbE1uVXdXUHZZVzJVQzVLZGh5Y0RCVXB2d2JSTzBobGhuY0FsZnlHbVdFZ2VTN2Q4Vy84RnIxUTgzVlcrbXNIR0Y0aW93d3REM2J6VS9RL0gxWURnV1d8ZWN0YStwUWdWWUFiOTIyWDVGWjdYYVdGZEVNcC9qODZacjlwWXRIcEJQRT0=/8" method="post"><div data-v-4c58e686="" class="form-preview" style="background-color: rgb(255, 255, 255); border-style: solid; border-width: 1px; border-color: rgb(204, 204, 204); position: relative;"><div data-v-4c58e686="" class="preview-heading"><h5 data-v-4c58e686="" style="font-family: Montserrat; font-weight: bold; color: rgb(0, 0, 0); font-size: 12px; text-align: center;">Get new posts by email:</h5></div> <div data-v-4c58e686="" class="preview-input-field"><input data-v-4c58e686="" type="email" name="email" placeholder="Enter your email" spellcheck="false" /></div> <div data-v-4c58e686="" class="preview-submit-button"><button data-v-4c58e686="" type="submit" style="font-family: Montserrat; font-weight: bold; color: rgb(255, 255, 255); font-size: 12px; text-align: center; background-color: rgb(0, 0, 0);">Subscribe</button></div></div></form> </div> <div class='clear'></div> </div><div class='widget HTML' data-version='1' id='HTML3'> <h2 class='title'>About the site</h2> <div class='widget-content'> <a href="https://www.righto.com/p/index.html">Contact info and site index</a> </div> <div class='clear'></div> </div><div class='widget PopularPosts' data-version='1' id='PopularPosts1'> <h2>Popular Posts</h2> <div class='widget-content popular-posts'> <ul> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2025/03/mother-of-all-demos-usb-keyset-interface.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_uYm0eIOdpLSpTwNkM2VHZNrJJQioG_drOB0g7wNl8769z3dSJGaLpgnc5Ph11Xs6zxgYx0dreFy_OiM6VHdKL_tNtW2tEA9oFHOBKojijDegzvnAgHpPpQgut8xktcTHA=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2025/03/mother-of-all-demos-usb-keyset-interface.html'>A USB interface to the "Mother of All Demos" keyset</a></div> </div> <div style='clear: both;'></div> </li> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2025/03/pentium-microcde-rom-circuitry.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_tRkTiYmTEkYysfD2qpEBr_16ZLpiSh7x2J37TI3WcagRWvMytAnfW2ah6HwaupjzsPTnb77uCk6fCgPHd4J3WUU74dQgym3hiCLyb6SKiBd2xcLtRdrH-LbRyluHZbNHVK4gbMBRRXHFF0hERBYjE=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2025/03/pentium-microcde-rom-circuitry.html'>Notes on the Pentium's microcode circuitry</a></div> </div> <div style='clear: both;'></div> </li> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2024/05/blog-post.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_t9RbSx6ThRISqlt67vI-potCqxV4h7oX-xHsZrgy_XVrjd2Pr0lhpeipqsaFzS2gvWxw_fSbysQDnhn2PxaJTti4hqP8UKogwxo5JWSVEkScyQqToUz-zAO3ft8clqQrgwVxuy1Q6Htk5ELdFx-ymv=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2024/05/blog-post.html'>Inside a vintage aerospace navigation computer of uncertain purpose</a></div> </div> <div style='clear: both;'></div> </li> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2025/03/pentium-multiplier-adder-reverse-engineered.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_vjyQK7lLPrDNd223iCyZNGH4RReUqRSsvwHAblzwix2WBwihXQ5ihlMzPBflWjdQ6q1NGBva4ThNu8fZOkLIxwWEv8hJJSZm1jNs_PV3tjVSM-gclnxJZ6id672qWSp7D7pCZYfpF8vzKw=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2025/03/pentium-multiplier-adder-reverse-engineered.html'>The Pentium contains a complicated circuit to multiply by three</a></div> </div> <div style='clear: both;'></div> </li> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_suWfHB4K4hv04jU1It3ZSCYZciT0g2i7sYt1et_LFHjJklK2zSAgxHH0CKcWhS8NGsaGsUc8dztmenrn1v_l_mqK5IxQ8GOOaOW7CLc2AAvRY=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html'>A Multi-Protocol Infrared Remote Library for the Arduino</a></div> </div> <div style='clear: both;'></div> </li> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2012/10/a-dozen-usb-chargers-in-lab-apple-is.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_ts3U9P3x84iGU9MeuMYBMrmAJlU8CByPMJgRRER5xg3dbnGa6huiR1AAnJNLMoVeO8h8yRSO0_pvr8RzSq6Rd2bnupsVvvzlP-zfg7bSRAd4G-VoK5wxpiSoeglhQ=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2012/10/a-dozen-usb-chargers-in-lab-apple-is.html'>A dozen USB chargers in the lab: Apple is very good, but not quite the best</a></div> </div> <div style='clear: both;'></div> </li> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2012/05/apple-iphone-charger-teardown-quality.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_u39Zx3eUkkcZoVKaRWYrKI5oy8aaIpVvklXsyY_mHyYDRfs5jOO64hlSZ-bEc4di1GZJHXTRi3RwYQ4kX7_Y6OnsNzmsGgSpKAaj94JfaRFPCB2Q-xvOMTOr81ObSCRV1Fm7iDKdr35Wo-sySTWtalrI8=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2012/05/apple-iphone-charger-teardown-quality.html'>Apple iPhone charger teardown: quality in a tiny expensive package</a></div> </div> <div style='clear: both;'></div> </li> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2014/09/mining-bitcoin-with-pencil-and-paper.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_vV4Aj_jtgiRpRiVpROCQQQk13NZhjiRZHYYrkywIrtNoqeVqrsfGmPlvoe6pojZOQyG2CMz2UClNYm88WaJ4s6H9ed-9PoN1tx_B6XsUUDZRb-_DVGfwLYfZU-iJTmxmRO=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2014/09/mining-bitcoin-with-pencil-and-paper.html'>Mining Bitcoin with pencil and paper: 0.67 hashes per day</a></div> </div> <div style='clear: both;'></div> </li> </ul> <div class='clear'></div> </div> </div><div class='widget BlogSearch' data-version='1' id='BlogSearch1'> <h2 class='title'>Search This Blog</h2> <div class='widget-content'> <div id='BlogSearch1_form'> <form action='http://www.righto.com/search' class='gsc-search-box' target='_top'> <table cellpadding='0' cellspacing='0' class='gsc-search-box'> <tbody> <tr> <td class='gsc-input'> <input autocomplete='off' class='gsc-input' name='q' size='10' title='search' type='text' value=''/> </td> <td class='gsc-search-button'> <input class='gsc-search-button' title='search' type='submit' value='Search'/> </td> </tr> </tbody> </table> </form> </div> </div> <div class='clear'></div> </div><div class='widget Label' data-version='1' id='Label1'> <h2>Labels</h2> <div class='widget-content cloud-label-widget-content'> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/386'>386</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/6502'>6502</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/8008'>8008</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/8085'>8085</a> </span> <span class='label-size label-size-4'> <a dir='ltr' href='http://www.righto.com/search/label/8086'>8086</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/8087'>8087</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/8088'>8088</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/aerospace'>aerospace</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/alto'>alto</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/analog'>analog</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/Apollo'>Apollo</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/apple'>apple</a> </span> <span class='label-size label-size-4'> <a dir='ltr' href='http://www.righto.com/search/label/arc'>arc</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/arduino'>arduino</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/arm'>arm</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/beaglebone'>beaglebone</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/bitcoin'>bitcoin</a> </span> <span class='label-size label-size-1'> <a dir='ltr' href='http://www.righto.com/search/label/c%23'>c#</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/cadc'>cadc</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/calculator'>calculator</a> </span> <span class='label-size label-size-4'> <a dir='ltr' href='http://www.righto.com/search/label/chips'>chips</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/css'>css</a> </span> <span class='label-size label-size-1'> <a dir='ltr' href='http://www.righto.com/search/label/datapoint'>datapoint</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/dx7'>dx7</a> </span> <span class='label-size label-size-5'> <a dir='ltr' href='http://www.righto.com/search/label/electronics'>electronics</a> </span> <span class='label-size label-size-1'> <a dir='ltr' href='http://www.righto.com/search/label/f%23'>f#</a> </span> <span class='label-size label-size-1'> <a dir='ltr' href='http://www.righto.com/search/label/fairchild'>fairchild</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/fpga'>fpga</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/fractals'>fractals</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/genome'>genome</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/globus'>globus</a> </span> <span class='label-size label-size-1'> <a dir='ltr' href='http://www.righto.com/search/label/haskell'>haskell</a> </span> <span class='label-size label-size-1'> <a dir='ltr' href='http://www.righto.com/search/label/HP'>HP</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/html5'>html5</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/ibm'>ibm</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/ibm1401'>ibm1401</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/ibm360'>ibm360</a> </span> <span class='label-size label-size-4'> <a dir='ltr' href='http://www.righto.com/search/label/intel'>intel</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/ipv6'>ipv6</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/ir'>ir</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/java'>java</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/javascript'>javascript</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/math'>math</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/microcode'>microcode</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/oscilloscope'>oscilloscope</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/Pentium'>Pentium</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/photo'>photo</a> </span> <span class='label-size label-size-4'> <a dir='ltr' href='http://www.righto.com/search/label/power%20supply'>power supply</a> </span> <span class='label-size label-size-4'> <a dir='ltr' href='http://www.righto.com/search/label/random'>random</a> </span> <span class='label-size label-size-5'> <a dir='ltr' href='http://www.righto.com/search/label/reverse-engineering'>reverse-engineering</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/sheevaplug'>sheevaplug</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/snark'>snark</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/space'>space</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/spanish'>spanish</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/synth'>synth</a> </span> <span class='label-size label-size-4'> <a dir='ltr' href='http://www.righto.com/search/label/teardown'>teardown</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/theory'>theory</a> </span> <span class='label-size label-size-1'> <a dir='ltr' href='http://www.righto.com/search/label/unicode'>unicode</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/Z-80'>Z-80</a> </span> <div class='clear'></div> </div> </div><div class='widget BlogArchive' data-version='1' id='BlogArchive1'> <h2>Blog Archive</h2> <div class='widget-content'> <div id='ArchiveList'> <div id='BlogArchive1_ArchiveList'> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2025/'> 2025 </a> <span class='post-count' dir='ltr'>(8)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2025/03/'> March </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2025/02/'> February </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2025/01/'> January </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/'> 2024 </a> <span class='post-count' dir='ltr'>(21)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/12/'> December </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/11/'> November </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/10/'> October </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/09/'> September </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/08/'> August </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/07/'> July </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/06/'> June </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/04/'> April </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/03/'> March </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/02/'> February </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/01/'> January </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate expanded'> <a class='toggle' href='javascript:void(0)'> <span class='zippy toggle-open'> ▼  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/'> 2023 </a> <span class='post-count' dir='ltr'>(35)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/12/'> December </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/11/'> November </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/10/'> October </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/09/'> September </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/08/'> August </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/07/'> July </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/04/'> April </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate expanded'> <a class='toggle' href='javascript:void(0)'> <span class='zippy toggle-open'> ▼  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/03/'> March </a> <span class='post-count' dir='ltr'>(4)</span> <ul class='posts'> <li><a href='http://www.righto.com/2023/03/reverse-engineering-globus-ink-soviet.html'>Reverse-engineering the Globus INK, a Soviet space...</a></li> <li><a href='http://www.righto.com/2023/03/8086-multiplication-microcode.html'>Reverse-engineering the multiplication algorithm i...</a></li> <li><a href='http://www.righto.com/2023/03/8086-register-codes.html'>Reverse-engineering the register codes for the 808...</a></li> <li><a href='http://www.righto.com/2023/03/reverse-engineering-electronics-in.html'>Reverse-engineering the electronics in the Globus ...</a></li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/02/'> February </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/01/'> January </a> <span class='post-count' dir='ltr'>(8)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/'> 2022 </a> <span class='post-count' dir='ltr'>(18)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/11/'> November </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/07/'> July </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/06/'> June </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/04/'> April </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/03/'> March </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/02/'> February </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/01/'> January </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/'> 2021 </a> <span class='post-count' dir='ltr'>(26)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/12/'> December </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/11/'> November </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/09/'> September </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/07/'> July </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/06/'> June </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/04/'> April </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/03/'> March </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/02/'> February </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/01/'> January </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/'> 2020 </a> <span class='post-count' dir='ltr'>(33)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/12/'> December </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/11/'> November </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/10/'> October </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/09/'> September </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/08/'> August </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/07/'> July </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/06/'> June </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/05/'> May </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/04/'> April </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/03/'> March </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/01/'> January </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/'> 2019 </a> <span class='post-count' dir='ltr'>(18)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/11/'> November </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/10/'> October </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/09/'> September </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/07/'> July </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/04/'> April </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/02/'> February </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/01/'> January </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/'> 2018 </a> <span class='post-count' dir='ltr'>(17)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/12/'> December </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/09/'> September </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/06/'> June </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/04/'> April </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/03/'> March </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/02/'> February </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/01/'> January </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/'> 2017 </a> <span class='post-count' dir='ltr'>(21)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/12/'> December </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/11/'> November </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/10/'> October </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/07/'> July </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/06/'> June </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/04/'> April </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/03/'> March </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/02/'> February </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/01/'> January </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/'> 2016 </a> <span class='post-count' dir='ltr'>(34)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/12/'> December </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/10/'> October </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/09/'> September </a> <span class='post-count' dir='ltr'>(8)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/08/'> August </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/07/'> July </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/06/'> June </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/04/'> April </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/03/'> March </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/02/'> February </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/01/'> January </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/'> 2015 </a> <span class='post-count' dir='ltr'>(12)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/12/'> December </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/11/'> November </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/10/'> October </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/05/'> May </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/03/'> March </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/02/'> February </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2014/'> 2014 </a> <span class='post-count' dir='ltr'>(13)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2014/12/'> December </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2014/10/'> October </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2014/09/'> September </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2014/05/'> May </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2014/03/'> March </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2014/02/'> February </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/'> 2013 </a> <span class='post-count' dir='ltr'>(24)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/11/'> November </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/09/'> September </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/08/'> August </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/07/'> July </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/06/'> June </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/04/'> April </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/03/'> March </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/02/'> February </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/01/'> January </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2012/'> 2012 </a> <span class='post-count' dir='ltr'>(10)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2012/12/'> December </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2012/11/'> November </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2012/10/'> October </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2012/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2012/03/'> March </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2012/02/'> February </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2011/'> 2011 </a> <span class='post-count' dir='ltr'>(11)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2011/12/'> December </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2011/07/'> July </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2011/05/'> May </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2011/04/'> April </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2011/03/'> March </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2011/02/'> February </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/'> 2010 </a> <span class='post-count' dir='ltr'>(22)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/12/'> December </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/11/'> November </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/10/'> October </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/06/'> June </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/05/'> May </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/04/'> April </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/03/'> March </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/01/'> January </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/'> 2009 </a> <span class='post-count' dir='ltr'>(22)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/12/'> December </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/11/'> November </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/09/'> September </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/08/'> August </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/07/'> July </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/06/'> June </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/04/'> April </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/03/'> March </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/02/'> February </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/01/'> January </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2008/'> 2008 </a> <span class='post-count' dir='ltr'>(27)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2008/07/'> July </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2008/06/'> June </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2008/05/'> May </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2008/04/'> April </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2008/03/'> March </a> <span class='post-count' dir='ltr'>(10)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2008/02/'> February </a> <span class='post-count' dir='ltr'>(6)</span> </li> </ul> </li> </ul> </div> </div> <div class='clear'></div> </div> </div></div> </aside> </div> </div> </div> <div style='clear: both'></div> <!-- columns --> </div> <!-- main --> </div> </div> <div class='main-cap-bottom cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> <footer> <div class='footer-outer'> <div class='footer-cap-top cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left footer-fauxborder-left'> <div class='fauxborder-right footer-fauxborder-right'></div> <div class='region-inner footer-inner'> <div class='foot no-items section' id='footer-1'></div> <table border='0' cellpadding='0' cellspacing='0' class='section-columns columns-2'> <tbody> <tr> <td class='first columns-cell'> <div class='foot no-items section' id='footer-2-1'></div> </td> <td class='columns-cell'> <div class='foot no-items section' id='footer-2-2'></div> </td> </tr> </tbody> </table> <!-- outside of the include in order to lock Attribution widget --> <div class='foot section' id='footer-3'><div class='widget Attribution' data-version='1' id='Attribution1'> <div class='widget-content' style='text-align: center;'> Powered by <a href='https://www.blogger.com' target='_blank'>Blogger</a>. </div> <div class='clear'></div> </div></div> </div> </div> <div class='footer-cap-bottom cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> </footer> <!-- content --> </div> </div> <div class='content-cap-bottom cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> </div> <script data-cfasync="false" src="/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js"></script><script type='text/javascript'> window.setTimeout(function() { document.body.className = document.body.className.replace('loading', ''); }, 10); </script> <script type="text/javascript" src="https://www.blogger.com/static/v1/widgets/2806328968-widgets.js"></script> <script type='text/javascript'> window['__wavt'] = 'AOuZoY7nxS9WFCLGR1YtcTYuJKJhriGlow:1744048147612';_WidgetManager._Init('//www.blogger.com/rearrange?blogID\x3d6264947694886887540','//www.righto.com/2023/03/','6264947694886887540'); _WidgetManager._SetDataContext([{'name': 'blog', 'data': {'blogId': '6264947694886887540', 'title': 'Ken Shirriff\x27s blog', 'url': 'http://www.righto.com/2023/03/', 'canonicalUrl': 'http://www.righto.com/2023/03/', 'homepageUrl': 'http://www.righto.com/', 'searchUrl': 'http://www.righto.com/search', 'canonicalHomepageUrl': 'http://www.righto.com/', 'blogspotFaviconUrl': 'http://www.righto.com/favicon.ico', 'bloggerUrl': 'https://www.blogger.com', 'hasCustomDomain': true, 'httpsEnabled': false, 'enabledCommentProfileImages': true, 'gPlusViewType': 'FILTERED_POSTMOD', 'adultContent': false, 'analyticsAccountNumber': 'UA-3782444-1', 'encoding': 'UTF-8', 'locale': 'en', 'localeUnderscoreDelimited': 'en', 'languageDirection': 'ltr', 'isPrivate': false, 'isMobile': false, 'isMobileRequest': false, 'mobileClass': '', 'isPrivateBlog': false, 'isDynamicViewsAvailable': true, 'feedLinks': '\x3clink rel\x3d\x22alternate\x22 type\x3d\x22application/atom+xml\x22 title\x3d\x22Ken Shirriff\x26#39;s blog - Atom\x22 href\x3d\x22http://www.righto.com/feeds/posts/default\x22 /\x3e\n\x3clink rel\x3d\x22alternate\x22 type\x3d\x22application/rss+xml\x22 title\x3d\x22Ken Shirriff\x26#39;s blog - RSS\x22 href\x3d\x22http://www.righto.com/feeds/posts/default?alt\x3drss\x22 /\x3e\n\x3clink rel\x3d\x22service.post\x22 type\x3d\x22application/atom+xml\x22 title\x3d\x22Ken Shirriff\x26#39;s blog - Atom\x22 href\x3d\x22https://www.blogger.com/feeds/6264947694886887540/posts/default\x22 /\x3e\n', 'meTag': '', 'adsenseHostId': 'ca-host-pub-1556223355139109', 'adsenseHasAds': false, 'adsenseAutoAds': false, 'boqCommentIframeForm': true, 'loginRedirectParam': '', 'view': '', 'dynamicViewsCommentsSrc': '//www.blogblog.com/dynamicviews/4224c15c4e7c9321/js/comments.js', 'dynamicViewsScriptSrc': '//www.blogblog.com/dynamicviews/51ad58472e92bd27', 'plusOneApiSrc': 'https://apis.google.com/js/platform.js', 'disableGComments': true, 'interstitialAccepted': false, 'sharing': {'platforms': [{'name': 'Get link', 'key': 'link', 'shareMessage': 'Get link', 'target': ''}, {'name': 'Facebook', 'key': 'facebook', 'shareMessage': 'Share to Facebook', 'target': 'facebook'}, {'name': 'BlogThis!', 'key': 'blogThis', 'shareMessage': 'BlogThis!', 'target': 'blog'}, {'name': 'X', 'key': 'twitter', 'shareMessage': 'Share to X', 'target': 'twitter'}, {'name': 'Pinterest', 'key': 'pinterest', 'shareMessage': 'Share to Pinterest', 'target': 'pinterest'}, {'name': 'Email', 'key': 'email', 'shareMessage': 'Email', 'target': 'email'}], 'disableGooglePlus': true, 'googlePlusShareButtonWidth': 0, 'googlePlusBootstrap': '\x3cscript type\x3d\x22text/javascript\x22\x3ewindow.___gcfg \x3d {\x27lang\x27: \x27en\x27};\x3c/script\x3e'}, 'hasCustomJumpLinkMessage': false, 'jumpLinkMessage': 'Read more', 'pageType': 'archive', 'pageName': 'March 2023', 'pageTitle': 'Ken Shirriff\x27s blog: March 2023'}}, {'name': 'features', 'data': {}}, {'name': 'messages', 'data': {'edit': 'Edit', 'linkCopiedToClipboard': 'Link copied to clipboard!', 'ok': 'Ok', 'postLink': 'Post Link'}}, {'name': 'template', 'data': {'name': 'custom', 'localizedName': 'Custom', 'isResponsive': false, 'isAlternateRendering': false, 'isCustom': true}}, {'name': 'view', 'data': {'classic': {'name': 'classic', 'url': '?view\x3dclassic'}, 'flipcard': {'name': 'flipcard', 'url': '?view\x3dflipcard'}, 'magazine': {'name': 'magazine', 'url': '?view\x3dmagazine'}, 'mosaic': {'name': 'mosaic', 'url': '?view\x3dmosaic'}, 'sidebar': {'name': 'sidebar', 'url': '?view\x3dsidebar'}, 'snapshot': {'name': 'snapshot', 'url': '?view\x3dsnapshot'}, 'timeslide': {'name': 'timeslide', 'url': '?view\x3dtimeslide'}, 'isMobile': false, 'title': 'Ken Shirriff\x27s blog', 'description': 'Computer history, restoring vintage computers, IC reverse engineering, and whatever', 'url': 'http://www.righto.com/2023/03/', 'type': 'feed', 'isSingleItem': false, 'isMultipleItems': true, 'isError': false, 'isPage': false, 'isPost': false, 'isHomepage': false, 'isArchive': true, 'isLabelSearch': false, 'archive': {'year': 2023, 'month': 3, 'rangeMessage': 'Showing posts from March, 2023'}}}]); _WidgetManager._RegisterWidget('_HeaderView', new _WidgetInfo('Header1', 'header', document.getElementById('Header1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_BlogView', new _WidgetInfo('Blog1', 'main', document.getElementById('Blog1'), {'cmtInteractionsEnabled': false}, 'displayModeFull')); _WidgetManager._RegisterWidget('_HTMLView', new _WidgetInfo('HTML2', 'sidebar-right-1', document.getElementById('HTML2'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_HTMLView', new _WidgetInfo('HTML3', 'sidebar-right-1', document.getElementById('HTML3'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_PopularPostsView', new _WidgetInfo('PopularPosts1', 'sidebar-right-1', document.getElementById('PopularPosts1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_BlogSearchView', new _WidgetInfo('BlogSearch1', 'sidebar-right-1', document.getElementById('BlogSearch1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_LabelView', new _WidgetInfo('Label1', 'sidebar-right-1', document.getElementById('Label1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_BlogArchiveView', new _WidgetInfo('BlogArchive1', 'sidebar-right-1', document.getElementById('BlogArchive1'), {'languageDirection': 'ltr', 'loadingMessage': 'Loading\x26hellip;'}, 'displayModeFull')); _WidgetManager._RegisterWidget('_AttributionView', new _WidgetInfo('Attribution1', 'footer-3', document.getElementById('Attribution1'), {}, 'displayModeFull')); </script> </body> </html>