{"id":100765,"date":"2019-01-22T23:00:00","date_gmt":"2019-01-23T14:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=100765"},"modified":"2019-03-18T11:09:38","modified_gmt":"2019-03-18T18:09:38","slug":"20190123-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20190122-00\/?p=100765","title":{"rendered":"The Intel 80386, part 3: Flags and condition codes"},"content":{"rendered":"<p>The flags register contains a bunch of stuff, but here are the flags easily accessible in the debugger: <\/p>\n<table BORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" CLASS=\"cp3\" STYLE=\"border: solid 1px black;border-collapse: collapse\">\n<tr>\n<th>Flag<\/th>\n<th>Clear\/Set<\/th>\n<th>Meaning<\/th>\n<th>Notes<\/th>\n<\/tr>\n<tr>\n<td>OF<\/td>\n<td>nv\/ov<\/td>\n<td>Overflow<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td>DF<\/td>\n<td>up\/dn<\/td>\n<td>Direction<\/td>\n<td>Must be <var>up<\/var> at function boundaries<\/td>\n<\/tr>\n<tr>\n<td>SF<\/td>\n<td>pl\/ng<\/td>\n<td>Sign<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td>IF<\/td>\n<td>ei\/di<\/td>\n<td>Interrupts<\/td>\n<td>Set if interrupts are enabled<\/td>\n<\/tr>\n<tr>\n<td>ZF<\/td>\n<td>nz\/zr<\/td>\n<td>Zero<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td>AF<\/td>\n<td>na\/ac<\/td>\n<td>Auxiliary carry<\/td>\n<td>Not used by C code<\/td>\n<\/tr>\n<tr>\n<td>PF<\/td>\n<td>pe\/po<\/td>\n<td>Parity<\/td>\n<td>Not used by C code<\/td>\n<\/tr>\n<tr>\n<td>CF<\/td>\n<td>nc\/cy<\/td>\n<td>Carry<\/td>\n<td><\/td>\n<\/tr>\n<\/table>\n<p>We&#8217;ll learn about the direction flag when we get to string operations. The important detail for now is that the direction flag must be clear (<var>up<\/var>) at function boundaries. <\/p>\n<p>Instructions for manipulating the interrupt flag are privileged, so you won&#8217;t see user-mode code messing with it. I wouldn&#8217;t normally have mentioned it, but the Windows disassembler displays the state of the interrupt flags in the register output, so I included it here just so you can see what it means (and then promptly forget about it). <\/p>\n<p>The auxiliary carry is used to indicate whether a carry occurred between bits 3 and 4. It is used by the binary coded decimal instructions. <\/p>\n<p>The parity is used to indicate whether the number of set bits in the least significant 8 bits of the result is odd or even. <\/p>\n<p>The <i>Clear\/Set<\/i> column denotes how the Windows disassembler represents flags in the register output: <\/p>\n<pre>\neax=00000000 ebx=00000000 ecx=9f490000 edx=00000000 esi=7f19e000 edi=00000000\neip=77a93dad esp=0048f844 ebp=0048f870 iopl=0         <span STYLE=\"border: solid black;border-width: 1px 0px 1px 1px\">nv up ei pl<\/span><span STYLE=\"border: solid black;border-width: 1px 1px 0px 0px\"> zr na pe nc<\/span>\ncs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             <span STYLE=\"border: solid 1px black;border-top-width: 0px\">efl=00000246<\/span>\n<\/pre>\n<p>The <var>efl<\/var> represents the value of the 32-bit flags register, and selected bits are parsed out and rendered as mnemonics on the line above. <\/p>\n<p>Various combinations of conditions can be expressed with condition codes. Note that many conditions have multiple mnemonics. The first one listed is the one the disassembler uses. <\/p>\n<table BORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" CLASS=\"cp3\" STYLE=\"border: solid 1px black;border-collapse: collapse\">\n<tr>\n<th>Code<\/th>\n<th>Meaning<\/th>\n<th>Condition<\/th>\n<th>Notes<\/th>\n<\/tr>\n<tr>\n<td><code>E<\/code><\/td>\n<td>Equal<\/td>\n<td ROWSPAN=\"2\"><code>ZF<\/code><\/td>\n<td ROWSPAN=\"2\"><\/td>\n<\/tr>\n<tr>\n<td><code>Z<\/code><\/td>\n<td>Zero<\/td>\n<\/tr>\n<tr>\n<td><code>NE<\/code><\/td>\n<td>Not equal<\/td>\n<td ROWSPAN=\"2\"><code>!ZF<\/code><\/td>\n<td ROWSPAN=\"2\"><\/td>\n<\/tr>\n<tr>\n<td><code>NZ<\/code><\/td>\n<td>Not zero<\/td>\n<\/tr>\n<tr>\n<td><code>A<\/code><\/td>\n<td>Above<\/td>\n<td ROWSPAN=\"2\"><code>!CF &amp;&amp; !ZF<\/code><\/td>\n<td ROWSPAN=\"2\">Unsigned greater than<\/td>\n<\/tr>\n<tr>\n<td><code>NBE<\/code><\/td>\n<td>Not below or equal<\/td>\n<\/tr>\n<tr>\n<td><code>AE<\/code><\/td>\n<td>Above or equal<\/td>\n<td ROWSPAN=\"3\"><code>!CF<\/code><\/td>\n<td ROWSPAN=\"2\">Unsigned greater than or equal<\/td>\n<\/tr>\n<tr>\n<td><code>NB<\/code><\/td>\n<td>Not below<\/td>\n<\/tr>\n<tr>\n<td><code>NC<\/code><\/td>\n<td>No carry<\/td>\n<td>No unsigned overflow<\/td>\n<\/tr>\n<tr>\n<td><code>B<\/code><\/td>\n<td>Below<\/td>\n<td ROWSPAN=\"3\"><code>CF<\/code><\/td>\n<td ROWSPAN=\"2\">Unsigned less than<\/td>\n<\/tr>\n<tr>\n<td><code>NAE<\/code><\/td>\n<td>Not above or equal<\/td>\n<\/tr>\n<tr>\n<td><code>C<\/code><\/td>\n<td>Carry set<\/td>\n<td>Unsigned overflow<\/td>\n<\/tr>\n<tr>\n<td><code>BE<\/code><\/td>\n<td>Below or equal<\/td>\n<td ROWSPAN=\"2\"><code>CF || ZF<\/code><\/td>\n<td ROWSPAN=\"2\">Unsigned less than or equal<\/td>\n<\/tr>\n<tr>\n<td><code>NA<\/code><\/td>\n<td>Not above<\/td>\n<\/tr>\n<tr>\n<td><code>G<\/code><\/td>\n<td>Greater<\/td>\n<td ROWSPAN=\"2\"><code>!(SF ^ OF) &amp;&amp; !ZF<\/code><\/td>\n<td ROWSPAN=\"2\">Signed greater than<\/td>\n<\/tr>\n<tr>\n<td><code>NLE<\/code><\/td>\n<td>Not less than or equal<\/td>\n<\/tr>\n<tr>\n<td><code>GE<\/code><\/td>\n<td>Greater than or equal<\/td>\n<td ROWSPAN=\"2\"><code>!(SF ^ OF)<\/code><\/td>\n<td ROWSPAN=\"2\">Signed greater than or equal<\/td>\n<\/tr>\n<tr>\n<td><code>NL<\/code><\/td>\n<td>Not less than<\/td>\n<\/tr>\n<tr>\n<td><code>L<\/code><\/td>\n<td>Less than<\/td>\n<td ROWSPAN=\"2\"><code>(SF ^ OF)<\/code><\/td>\n<td ROWSPAN=\"2\">Signed less than<\/td>\n<\/tr>\n<tr>\n<td><code>NGE<\/code><\/td>\n<td>Not greater than or equal<\/td>\n<\/tr>\n<tr>\n<td><code>LE<\/code><\/td>\n<td>Less than or equal<\/td>\n<td ROWSPAN=\"2\"><code>(SF ^ OF) || ZF<\/code><\/td>\n<td ROWSPAN=\"2\">Signed less than or equal<\/td>\n<\/tr>\n<tr>\n<td><code>NG<\/code><\/td>\n<td>Not greater than<\/td>\n<\/tr>\n<tr>\n<td><code>S<\/code><\/td>\n<td>Sign<\/td>\n<td><code>SF<\/code><\/td>\n<td>Negative<\/td>\n<\/tr>\n<tr>\n<td><code>NS<\/code><\/td>\n<td>No sign<\/td>\n<td><code>!SF<\/code><\/td>\n<td>Positive or zero<\/td>\n<\/tr>\n<tr>\n<td><code>O<\/code><\/td>\n<td>Overflow<\/td>\n<td><code>OF<\/code><\/td>\n<td>Signed overflow<\/td>\n<\/tr>\n<tr>\n<td><code>NO<\/code><\/td>\n<td>No overflow<\/td>\n<td><code>!OF<\/code><\/td>\n<td>No signed overflow<\/td>\n<\/tr>\n<tr>\n<td><code>P<\/code><\/td>\n<td>Parity<\/td>\n<td ROWSPAN=\"2\"><code>PF<\/code><\/td>\n<td ROWSPAN=\"2\">Even number of bits set<\/td>\n<\/tr>\n<tr>\n<td><code>PE<\/code><\/td>\n<td>Parity even<\/td>\n<\/tr>\n<tr>\n<td><code>NP<\/code><\/td>\n<td>No parity<\/td>\n<td ROWSPAN=\"2\"><code>!PF<\/code><\/td>\n<td ROWSPAN=\"2\">Odd number of bits set<\/td>\n<\/tr>\n<tr>\n<td><code>PO<\/code><\/td>\n<td>Parity odd<\/td>\n<\/tr>\n<\/table>\n<p>The overflow and parity conditions are not normally used by C code. Note also that many flags are not testable via condition codes. (Poor auxiliary carry flag. Nobody loves you.) <\/p>\n<p>There are a few instructions for directly manipulating selected flags:<\/p>\n<pre>\n    STC         ; set carry\n    CLC         ; clear carry\n    CMC         ; complement (toggle) carry\n\n    STD         ; set direction (go down)\n    CLD         ; clear direction (go up)\n<\/pre>\n<p>Controlling the interrupt flag is a privileged instruction, so you won&#8217;t see it in user-mode code. There are no instructions for directly manipulating the other flags, but you can manipulate them indirectly by performing an arithmetic operation with a known effect on flags. For example, you can force <var>ZF<\/var> to be set by performing a calculation whose result is known to be zero, such as <code>XOR EAX, EAX<\/code>. <\/p>\n<p>Okay, that was extremely boring, but it had to be done. <a HREF=\"http:\/\/devblogs.microsoft.com\/oldnewthing\/20190124-00\/?p=100775\">Next time<\/a>, we&#8217;ll start doing arithmetic. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>It&#8217;s just a bunch of stuff that happened.<\/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-100765","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-history"],"acf":[],"blog_post_summary":"<p>It&#8217;s just a bunch of stuff that happened.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/100765","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=100765"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/100765\/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=100765"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=100765"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=100765"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}