Assembly 程序集比较标志理解

Assembly 程序集比较标志理解,assembly,x86,eflags,Assembly,X86,Eflags,我正在努力理解汇编程序中的以下代码片段: if ( EAX >= 5 ) EBX = 1; else EBX = 2;" 在汇编程序中,可以这样编写(根据我的书),模拟通常使用的“更简单”分支,一次只查看一个标志: 1 cmp eax, 5 ;(assuming eax is signed) 2 js signon ;goto signon if SF = 1 3 jo elseblock ;goto elseb

我正在努力理解汇编程序中的以下代码片段:

if ( EAX >= 5 )
  EBX = 1;
else
  EBX = 2;"
在汇编程序中,可以这样编写(根据我的书),模拟通常使用的“更简单”分支,一次只查看一个标志:

1     cmp eax, 5       ;(assuming eax is signed)
2     js signon        ;goto signon if SF = 1
3     jo elseblock     ;goto elseblock if OF = 1 and SF = 0
4     jmp thenblock    ;goto thenblock if SF = 0 and OF = 0
5 signon:
6     jo thenblock     ;goto thenblock if SF = 1 and OF = 1
7 elseblock:
8     mov ebx, 2
9     jmp next
10 thenblock:
11    mov ebx, 1
12    next:
我可以理解,结果标志可以是:(if(EAX>=5)):

SF=0和OF=0 但我无法理解这些旗帜是怎样的: SF=1和OF=1?计算结果是什么

为了澄清我的意思:


如果eax处于负下限,则可能通过减去5溢出到正边界。如果它在正上界,它就不能通过减去5而溢出到负上界。

用3位数字来考虑这些更容易,它都可以缩放。嗯,如果这是有符号的(您没有在高级代码中指定/post),那么四位更好,因为您使用了5位。浏览5附近的数字(显示alu的输出)

现在您必须了解硬件是如何工作的。有些处理器系列在执行减法运算时,会反转alu输出的进位标志,而其他处理器则不会。无论哪种方式,你都可以在5-5点看到状态变化。你不需要这里的进位标志,代码不使用它

如果你在做符号数学,那么也试试负数

0000 - 0101 = 0000 + 1010 + 1 = 01011  
1111 - 0101 = 1111 + 1010 + 1 = 11010
1110 = 0101 = 1110 + 1010 + 1 = 11001
这就为这个问题提供了一些线索

有符号溢出定义为进位不等于加法器msbit上的进位。这可能会变得混乱,所以我们只需要知道边界在哪里

0111 - 0101 = 7 - 5 = 2
0110 - 0101 = 6 - 5 = 1
0101 - 0101 = 5 - 5 = 0
0100 - 0101 = 4 - 5 = -1
0011 - 0101 = 3 - 5 = -2
等等。使用这个4位模型,在有符号解释中,我们被限制在+7(0b0111)到-8(0b1000)。所以在-3-5之后我们会遇到麻烦:

1110 - 0101 = 1110 + 1010 + 1 = 11001 , -2 - 5 = -7
1101 - 0101 = 1101 + 1010 + 1 = 11000 , -3 - 5 = -8
1100 - 0101 = 1100 + 1010 + 1 = 10111 , -4 - 5 = 7 (-9 if we had more bits)
1011 - 0101 = 1011 + 1010 + 1 = 10110 , -5 - 5 = 6 (-10 if we had more bits)
1010 - 0101 = 1010 + 1010 + 1 = 10101 , -6 - 5 = 5 (-11 if we had more bits)
1001 - 0101 = 1001 + 1010 + 1 = 10100 , -7 - 5 = 4 (-12 if we had more bits)
1000 - 0101 = 1000 + 1010 + 1 = 10011 , -8 - 5 = 3 (-13 if we had more bits)
后五个是有符号溢出,有符号结果不能用可用位数表示。(请记住,我们现在使用的是四位系统,最上面的一位是进位,当您查看结果时,可以直观地删除它)

有符号标志只是结果的msbit,这也改变了有趣的边界。设置有符号标志(结果的msbit)的情况是小于5的正值(eax)和不会导致有符号溢出的负数(+4到-3)。所有这些都在if(EAX>=5)中 EBX=1; 其他的 EBX=2;"


是的,我理解,但是eax怎么会溢出到一个负数?我可以理解SF=0和OF=1如何不满足条件,但不理解SF=1和OF=1如何满足条件。你在读什么书/文档/网站?SF=1表示结果为负数,OF=1表示操作导致有符号操作数的溢出/下溢。如果两者都设置了,这意味着左操作数是一个大的正数,右操作数是一个小的负数,足以导致结果从正转为负。当第二个操作数是5时,这是不可能的。(编辑:在我看来,学习这一点的最佳书籍是。)这是什么书?当一本简单的
jge
也能做同样的事情并且更具可读性时,为什么它要处理多个条件分支呢?我认为整个
js/jo/jmp/jo
块都是从一个通用的解决方案复制粘贴而来的,而没有费心去适应特定的上下文。这本书是每日WTF吗?那是可怕的代码,我希望这只是一个奇怪的例子,我从来没有在任何地方的生产中遇到过这样的事情!嗨!在研究了你的答案后,我有一些问题。首先,它不应该是“后五个是有符号的溢出”而不是“后两个…”。。。“我还有一个问题是关于标志的。您说符号标志只是结果的msbit。在您的回答中,您说符号标志设置在eax正值上,感谢您发现这些错误,这有意义吗?还是我的回答中仍然有错误?非常感谢您更新@dwelch。你真的帮了我这个忙!
1110 - 0101 = 1110 + 1010 + 1 = 11001 , -2 - 5 = -7
1101 - 0101 = 1101 + 1010 + 1 = 11000 , -3 - 5 = -8
1100 - 0101 = 1100 + 1010 + 1 = 10111 , -4 - 5 = 7 (-9 if we had more bits)
1011 - 0101 = 1011 + 1010 + 1 = 10110 , -5 - 5 = 6 (-10 if we had more bits)
1010 - 0101 = 1010 + 1010 + 1 = 10101 , -6 - 5 = 5 (-11 if we had more bits)
1001 - 0101 = 1001 + 1010 + 1 = 10100 , -7 - 5 = 4 (-12 if we had more bits)
1000 - 0101 = 1000 + 1010 + 1 = 10011 , -8 - 5 = 3 (-13 if we had more bits)
cmp eax,5
jae biggerthan
mov ebx,2
jmp out
.biggerthan
mov ebx,1
.out