1

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

if ( EAX >= 5 )
  EBX = 1;
else
  EBX = 2;"

在汇编程序中,这可以写成如下(根据我的书),模拟您通常在“更简单”的分支中使用的jge指令,这些分支一次只查看一个标志:

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:

我可以理解生成的标志可以是:(如果( EAX >= 5 )):

SF = 0 & OF = 0 但我不明白标志是怎么回事:SF = 1 & OF = 1?什么计算给出了这个?

为了澄清我的意思:

如果 eax 在负下限,它可能会通过减去 5 溢出到正数。如果它在正数上限,它不能通过减去 5 溢出到负数?

4

2 回答 2

1

用 3 位数字来考虑这些要容易得多,它都是可伸缩的。嗯,如果这是签名的(您没有在高级代码中指定/发布),那么四位更好,因为您使用了 5。遍历 5 附近的数字(这显示了 alu 的输出)

cmp reg,5
0111 - 0101 = 0111 + 1010 + 1 = 10010
0110 - 0101 = 0110 + 1010 + 1 = 10001
0101 - 0101 = 0101 + 1010 + 1 = 10000
0100 - 0101 = 0100 + 1010 + 1 = 01111
0011 - 0101 = 0011 + 1010 + 1 = 01110

现在您必须了解硬件的工作原理。某些处理器系列在执行减法运算时会反转来自 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,这也改变了有趣的边界。设置有符号标志(结果的毫秒位)的情况是低于 5 的正 (eax) 值和不导致有符号溢出的负数(+4 到 -3)。所有这些都在 <5 类别中,因此他们希望得到 2 的结果。第一个测试查找设置了符号的情况,为什么还要麻烦然后测试有符号溢出?这是没有意义的,我们已经知道所有签名的结果都在小于 5 的类别中。如果签名溢出不会伤害额外的跳跃。

因此,如果您通过 js 登录失败,则符号位关闭,即大于或等于 5 的数字(希望结果为 1)或结果为负数足以导致有符号溢出(希望结果为 2)。所以 jo elseblock 通过提取 2 个案例的结果(有符号溢出,非常否定)来对这两个案例进行排序。jmp thenblock 取大于 5 的正数。

在我看来,你在这里做有符号数学(使用有符号溢出标志有点明显)。由于您使用 5 来比较和签名数学,因此您的系统中需要 4 位或更多位来实现此代码,因此 8、32、64、123456 位,它与 4 位系统的工作方式相同并不重要(对于这个比较)。我发现最小化位数来进行分析更容易。像这样的硬编码比较使它变得容易得多,就像上面、at和下面的手工计算结果一样。然后遍历有符号数的全零(零)到全一(减一),并且非常负数进入有符号溢出范围。对于无符号数字,它更容易一些,但过程相同。

于 2012-12-31T16:00:18.713 回答
-1

如果 (EAX >= 5) EBX = 1; 否则 EBX = 2;"

cmp eax,5
jae biggerthan
mov ebx,2
jmp out
.biggerthan
mov ebx,1
.out
于 2013-05-24T13:02:09.627 回答