{"id":102626,"date":"2019-06-27T07:00:00","date_gmt":"2019-06-27T14:00:00","guid":{"rendered":"http:\/\/devblogs.microsoft.com\/oldnewthing\/?p=102626"},"modified":"2019-06-27T18:25:00","modified_gmt":"2019-06-28T01:25:00","slug":"20190627-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20190627-00\/?p=102626","title":{"rendered":"Why does the <CODE>Get&shy;Version<\/CODE> function report the major version in the low-order byte, and the minor version in the high-order byte?"},"content":{"rendered":"<p><a href=\"https:\/\/twitter.com\/WindowsDocs\/status\/1124329256736251904\"> Laura Butler wonders<\/a> whose idea it was to have the <code>Get\u00adVersion<\/code> function report the major version in the low-order byte, and the minor version in the high-order byte. This is completely messed up: You clearly should put the major version in the high-order byte and the minor version in the low-order byte, so that you can do things like<\/p>\n<pre>if (HypotheticalBetterGetVersion() &gt;= 0x030A) {\r\n  \/\/ version is at least 3.10\r\n}\r\n<\/pre>\n<p>Instead, as things stand today, the major version in the low-order byte, and the minor version in the high-order byte, so version 3.10 is reported as the value <code>0x0A03<\/code>, which leads to mistakes like this:<\/p>\n<pre>\/\/ Code in italics is wrong\r\n<i>if (GetVersion() &gt;= 0x0A03)<\/i> {\r\n  \/\/ incorrect check for version \u2265 3.10\r\n}\r\n<\/pre>\n<p>Why is the version number reported in such a strange way?<\/p>\n<p>Rewind to MS-DOS.<\/p>\n<p>MS-DOS has a <i>Get Version<\/i> system call, and it returns the operating system version in the same reversed way, with the major version in the low-order byte, and the minor version in the high-order byte.<\/p>\n<p>The thinking was that programs will almost always be checking the major version exclusively, because the only time you&#8217;d need to check the minor version is if you needed to check for some feature that was added in a minor version. But by definition, minor versions don&#8217;t add many features (right?), so checking for the minor version should be very rare.<\/p>\n<p>During this era, programs were written in assembly language, and that&#8217;s the detail that shines light on the unusual format of the version number.<\/p>\n<p>On the 8086, the 16-bit <code>AX<\/code> register can be treated as a 16-bit value, or it can be treated as two 8-bit values. If you treat it as two 8-bit values, then the high-order byte is called <code>AH<\/code>, and the low-order byte is called <code>AL<\/code>.<\/p>\n<p>The 8086 instructions to compare the values in these registers are encoded as follows:<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"1\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th>Instruction<\/th>\n<th>Encoding<\/th>\n<\/tr>\n<tr>\n<td><code>CMP AL, 03h<\/code><\/td>\n<td><tt>3C 03<\/tt><\/td>\n<\/tr>\n<tr>\n<td><code>CMP AH, 03h<\/code><\/td>\n<td><tt>80 FC 03<\/tt><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Since almost everyone will be comparing the major version, we should put the major version in the location that is most efficient to consume, and that would be the <code>AL<\/code> register. Putting the value there permits a shorter instruction encoding than if the value had been in the <code>AH<\/code> register.<\/p>\n<p>It saves a byte!<\/p>\n<p>The IBM PC came in two memory configurations, 16KB and 64KB. If you had shelled out the big bucks for the 64KB version, that one byte is 0.0015% of your total memory. Scaled to a modern 8GB system, choosing this format for the version number saves 128KB.<\/p>\n<p>Windows adopted the version numbering scheme from MS-DOS, and that&#8217;s why the <code>Get\u00adVersion<\/code> function returns the major and minor versions in reverse order.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It seemed like a good idea at the time.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[2],"class_list":["post-102626","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-history"],"acf":[],"blog_post_summary":"<p>It seemed like a good idea at the time.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/102626","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=102626"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/102626\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=102626"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=102626"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=102626"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}