{"id":60,"date":"2008-04-03T15:09:16","date_gmt":"2008-04-03T17:09:16","guid":{"rendered":"http:\/\/www.ragestorm.net\/blogs\/?p=60"},"modified":"2008-04-03T15:21:06","modified_gmt":"2008-04-03T17:21:06","slug":"aaaaas","status":"publish","type":"post","link":"https:\/\/www.ragestorm.net\/blogs\/?p=60","title":{"rendered":"AAA\/AAS Quirk"},"content":{"rendered":"<p>As I was working on the simulation of these two instructions I found that they have some quirk, although the algorithms for these instructions are described in Intel&#8217;s specs, which (seems to) make the output defined for <em>all<\/em> inputs, it is not the case. Everytime I finish writing an implementation for a specific instruction I add that instruction to my unit tests. The instruction is being simulated with random(and some smarter)\u00a0input and then checked against pure native execution to see if the results are correct. So this way I found a quirk for a range of input that reveals how the instruction is really implemented (microcode stuff prolly) rather than how it&#8217;s documented.<\/p>\n<p>AL = AL + 6 is done when the AF is set or low nibble of AL is above 9. According to the documentation the destination register is AL, but in reality the destination register is <strong>AX<\/strong>. Now how do we know such a thing?<\/p>\n<p>If we try the following input:<br \/>\nmov al, 0xff<br \/>\naaa<\/p>\n<p>The result will be 0x205, rather than 0x105 (which is what we expect according to the docs).<\/p>\n<p>What really happens is that we supply a number that when added with 6 creates a carry into AH, thus incrementing AH by 1. Then looking at the docs again, we see that if AL was added with 6, it also increments AH by 1 manually. Thus AH is really incremented by 2. :P<\/p>\n<p>The question is why they do AX = AX + 6, rather then operating on AL. No, actually the biggest question is why I get this same behavior on an AMD\u00a0processor (whereas I work on an Intel processor). And we already by my last post about SHLD that they don&#8217;t work the same in some undefined behavior aspects (although some people believe AMD copied Intel&#8217;s architecture and <em>implementation<\/em>)&#8230;<\/p>\n<p>There might be some people who will say that I went too far with testing this instruction, because I, somewhat, supply an input which is not in the valid range (it&#8217;s unpacked BCD after all), which therefore I must not rely on the output. The thing is, the algorithm is defined well to receive any input I pass it, hence I expect it to work for even <em>undefined<\/em> input. Though I believe there is no such a thing as undefined input, only undefined output, and that&#8217;s why I implemented my instrction as they both did. Specifically where they both didn&#8217;t state anything about undefined input\/output, which makes my case stronger. Anyway, the point is they don&#8217;t tell us something here, the implementation is not similar to this documented in both AMD\/Intel docs.<\/p>\n<p>This quirk works the same for AAS, where instead of doing AL = AL -6, it&#8217;s really AX = AX &#8211; 6. I also tried to see whether they work on the whole EAX, but I saw that the high word wasn&#8217;t changed (by carry\/borrow). And I also tried to see if this ill behavior is found in both DAA\/DAS, but no.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>As I was working on the simulation of these two instructions I found that they have some quirk, although the algorithms for these instructions are described in Intel&#8217;s specs, which (seems to) make the output defined for all inputs, it is not the case. Everytime I finish writing an implementation for a specific instruction I [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spay_email":"","jetpack_publicize_message":""},"categories":[5,19,10],"tags":[],"jetpack_featured_media_url":"","jetpack_publicize_connections":[],"jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/sbWKd-aaaaas","_links":{"self":[{"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=\/wp\/v2\/posts\/60"}],"collection":[{"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=60"}],"version-history":[{"count":0,"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=\/wp\/v2\/posts\/60\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=60"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=60"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ragestorm.net\/blogs\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=60"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}