【问题标题】:How does sign contraction work from 16 bit to 8 bit?符号收缩如何从 16 位工作到 8 位?
【发布时间】:2022-01-22 16:19:04
【问题描述】:

我如何签署合同 ff12。这是一个负数,但我需要在这里删除所有 FF,但如果我这样做,它就会变成一个正数。


“符号收缩”的一个定义can be found in this The Art of Assembly 的在线副本,与 x86 cbw 之类的符号扩展相反。

符号收缩,将具有一些位数的值转换为具有较少位数的相同值,有点麻烦。标志扩展永远不会失败。给定一个 m 位有符号值,您始终可以使用符号扩展将其转换为 n 位数字(其中 n > m)。不幸的是,给定一个 n 位数,如果 m

【问题讨论】:

  • 它不适合,因为 ff12-238 但 8 位范围是 -128+127
  • 不,不能。它超出了 8 位有符号的范围。
  • 没有自然的方法可以使该数字 (-238) 适合 8 位;如果你强制它,它会被截断,这是溢出的另一种说法,并且在溢出时,预期的值会丢失,你得到的东西会变成其他值。该数字需要从第 2^8 位位置开始的至少一个符号位。我从来没有听说过符号收缩这个词,那是什么——你有参考吗?
  • 你想要什么结果?饱和而不是截断,就像布伦丹的答案所示?我搜索了“符号收缩”,因为我从未听说过该术语,并且我发现的第一个命中(我在问题中编辑)将其描述为保值,与符号扩展相反。并清楚地解释了这并不总是可能的;有些数字不适合 8 位。如果您想了解截断的替代方法,edit 您的问题就是这么说。
  • 正如书中指出的那样,“不幸的是,给定一个 n 位数,如果 m

标签: assembly type-conversion twos-complement truncation signed-integer


【解决方案1】:

符号收缩如何从 16 位到 8 位?

没有(最高 8 位,包括符号位,如果值太大而无法放入 8 位,则简单地丢弃)。

相反,您必须自己实现它。

如果“收缩”是“尽可能多地保留位”,那么它可能会变成这样:

    add ax,ax   ;carry flag = sign bit, al = lowest 7 bits shifted left
    rcr al,1    ;al = original sign bit with original lowest 7 bits

对于您的测试值 0xFF12(或十进制的 -238),这在 add 之后变为“设置进位标志的 0xFE24”,然后在 rcr 之后变为 0x92(或十进制的 -110)。

更多示例(包括极端案例):

0xFF80 (or -128) -> "0xFF00 with carry flag set" = 0x80 (or -128)

0xFF00 (or -256) -> "0xFE00 with carry flag set" = 0x80 (or -128)

0x0000 -> "0x0000 with carry flag clear" = 0x00

0x007F (or +127) -> "0x00FE with carry flag clear" = 0x007F (or +127)

0x00FF (or +255) -> "0x01FE with carry flag clear" = 0x007F (or +127)

如果“收缩”是“饱和”(钳位值),那么它可能类似于:

    mov bx,ax    ;bx = original 16-bit value
    cbw          ;ax = 16-bit extension of original value in AL
    cmp ax,bx    ;Did the original value fit in 8 bits?
    je .done     ; yes, AL is correct (no saturation needed)

    add bx,bx    ;carry flag = original sign bit
    mov al,0x7F
    adc al,0     ;al = 0x80 (if value was negative) or 0x7F (if value was positive)
.done:

我不确定是否有更好的方法(看起来很糟糕,我怀疑我的大脑今天没有工作)。

【讨论】:

  • 什么是符号收缩? (我知道截断和溢出,但从未听说过符号收缩作为术语、技术、数学运算或要执行的操作。)
  • @ErikEidt:哦,你说得对。修复以覆盖饱和度(我能想到的唯一其他可能性)。
  • 为什么饱和度应该返回 -128 或 0,如您的示例所示?我希望 -128 或 127。
  • @ecm:因为这是一个错误 - 现在已修复 :-)
  • 请注意,x86 内置了带有 MMX 或 SSE2 的签名饱和packsswb xmm0, xmm0felixcloutier.com/x86/packsswb:packssdw。回复:你的 add/mov/adc,这是合理的。 GCC 类似地分支,然后使用 test / setle / add 127 产生 127 或 -128。 godbolt.org/z/ocbhWPKra。我认为如果您使用的是具有高效换档 (386) 的 CPU,那可能是 shr ax, 15 / add al, 127。 clang 一直使用 cmov。另一个使用>=0 正确测试符号位的版本确实让GCC 使用shr ax, 15。 (在 64 位模式下,后跟 add eax,127 P6 系列上的部分注册停止!)
猜你喜欢
  • 2015-09-06
  • 1970-01-01
  • 2021-07-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-14
  • 1970-01-01
  • 2012-10-11
相关资源
最近更新 更多