理解英特尔 SUB 指令
Understanding intel SUB instruction
我目前正在努力加深对汇编代码的理解,几周以来我一直被一个看似简单的指令所困扰:
sub al, BYTE PTR [ebp+4]
假设eax = 0x11223300
和BYTE PTR [ebp+4] = 0xaa
在上述指令后eax
的值是多少?
据我了解,al
只能影响 eax
中的最后一个字节(在本例中为 0x00
),因此程序会尝试计算 0x00 - 0xaa
。但是结果是负数,我不知道结果是否只是 0x00
或者数字是否自动转换为负数,在这种情况下 0xaa
本身可以被视为负值这意味着我们正在尝试计算 0x00 - (-0x2a)
= 0x2a
The SUB instruction performs integer subtraction. It evaluates the
result for both signed and unsigned integer operands and sets the OF
and CF flags to indicate an overflow in the signed or unsigned result,
respectively. The SF flag indicates the sign of the signed result.
但它只描述了标志的一些行为,我不知道如何在这种特定情况下寻找更多关于这些的信息。
你可以用两种不同的方式来思考,它们给出的结果是一样的。
作为无符号,计算结果为mod 256。所以0x00 – 0xaa mod 0x100 = 0x56
。
如签名,0xaa
代表–0x56
。 (不是问题中的 –0x2a
。)
所以,0x00 – (–0x56) = 0x56
.
From what I understand, al can only affect the last byte in eax ...
这是正确的。
But the result being negative ...
现在变得复杂了。
就像大多数 CPU 一样,x86 不区分无符号整数和 "twos-complement" 有符号整数。
这意味着 0xaa
可能表示 170 或 (-86),程序员或编译器的任务是解释该值(如果 0xaa
表示 170 或 -86)。
如果只考虑计算的低位,这是可能的。示例:
0 + 170 = 0x000000AA
0 + (-86) = 0xFFFFFFAA
或:
0 - 170 = 0xFFFFFF56
0 - (-86) = 0x00000056
以上两个结果,低8位相等
所以对于只修改低8位的指令,它并不关心0xaa
是170还是(-86)。
x86 的 SUB
指令会将结果的低 8 位写入寄存器,"throw away" 高 24 位。
CPU 设置 "flags" 寄存器中的 4 位,以将关于这 24 位的附加信息传递给程序。
if the result would simply be 0x00
一些 CPU 支持这样操作的指令:如果 "correct" 结果为负,则减法的结果为 0。
但是,这样的 CPU 通常有两个不同的 SUB
指令:一个计算类似于 x86 的 SUB
指令,另一个指令将结果饱和为 0。
我目前正在努力加深对汇编代码的理解,几周以来我一直被一个看似简单的指令所困扰:
sub al, BYTE PTR [ebp+4]
假设eax = 0x11223300
和BYTE PTR [ebp+4] = 0xaa
在上述指令后eax
的值是多少?
据我了解,al
只能影响 eax
中的最后一个字节(在本例中为 0x00
),因此程序会尝试计算 0x00 - 0xaa
。但是结果是负数,我不知道结果是否只是 0x00
或者数字是否自动转换为负数,在这种情况下 0xaa
本身可以被视为负值这意味着我们正在尝试计算 0x00 - (-0x2a)
= 0x2a
The SUB instruction performs integer subtraction. It evaluates the result for both signed and unsigned integer operands and sets the OF and CF flags to indicate an overflow in the signed or unsigned result, respectively. The SF flag indicates the sign of the signed result.
但它只描述了标志的一些行为,我不知道如何在这种特定情况下寻找更多关于这些的信息。
你可以用两种不同的方式来思考,它们给出的结果是一样的。
作为无符号,计算结果为mod 256。所以0x00 – 0xaa mod 0x100 = 0x56
。
如签名,0xaa
代表–0x56
。 (不是问题中的 –0x2a
。)
所以,0x00 – (–0x56) = 0x56
.
From what I understand, al can only affect the last byte in eax ...
这是正确的。
But the result being negative ...
现在变得复杂了。
就像大多数 CPU 一样,x86 不区分无符号整数和 "twos-complement" 有符号整数。
这意味着 0xaa
可能表示 170 或 (-86),程序员或编译器的任务是解释该值(如果 0xaa
表示 170 或 -86)。
如果只考虑计算的低位,这是可能的。示例:
0 + 170 = 0x000000AA
0 + (-86) = 0xFFFFFFAA
或:
0 - 170 = 0xFFFFFF56
0 - (-86) = 0x00000056
以上两个结果,低8位相等
所以对于只修改低8位的指令,它并不关心0xaa
是170还是(-86)。
x86 的 SUB
指令会将结果的低 8 位写入寄存器,"throw away" 高 24 位。
CPU 设置 "flags" 寄存器中的 4 位,以将关于这 24 位的附加信息传递给程序。
if the result would simply be 0x00
一些 CPU 支持这样操作的指令:如果 "correct" 结果为负,则减法的结果为 0。
但是,这样的 CPU 通常有两个不同的 SUB
指令:一个计算类似于 x86 的 SUB
指令,另一个指令将结果饱和为 0。