【问题标题】:How should I infer the C data type of an addb instruction on a x86-64 machine?我应该如何推断 x86-64 机器上 addb 指令的 C 数据类型?
【发布时间】:2019-07-01 19:42:11
【问题描述】:

我有以下 C 代码,其中 v 和 b 都是有符号数据类型或指向有符号数据类型的指针。我们也知道 sizeof(b) = 2。

*v+=b

x86-64 上的汇编代码是...

addb %sil, (%rcx)

问题是 v 和 b 的 C 数据类型是什么?

我知道 %sil 对应于 b 而 %rcx 对应于 v。 但是,解决方案说“因为 b 的低位字节被添加到 %rcx 指向的字节,所以 v 必须是 char* 类型。”

我不明白为什么 v 必须是 char*。为什么不能短*?

注意:这可能是印刷错误,因为在本书的勘误表上已经发布了关于这个问题的另一个印刷错误。

【问题讨论】:

  • addb 中的b 表示字节,8 位。 sil 也是一个 8 位寄存器。因此,它必须是 8 位值,即(可能)char 而不是 short。它不能是short(假设是 16 位),因为加法不能正确处理从低 8 位到高 8 位的进位。哦,We also know that sizeof(b) = 2???你确定吗?如果有印刷错误,就是这样。 sizeof(b) 应该是 1
  • 我不完全确定为什么,但我刚刚检查了这本书,b 是书中使用的两个字节。它可能与平台有关?对于这个问题,我们应该假设 addb 增加了两个字节,因为它是书中使用的假设。
  • 虽然您可以在char 中添加short(带有截断),这样即使误导也可能被认为是正确的。
  • 正如解决方案所说,这是因为某些值“添加到 %rcx 指向的字节”。 short 不仅仅是一个字节。
  • @melpomene 我可能错了,但我认为 (%rcx) 会从 %rcx 引用的位置获取两个字节(因为它被 addb 使用)?

标签: c assembly types x86-64


【解决方案1】:

我不明白为什么 v 必须是 char*。为什么不能短*?

不可能是short*,因为addb是字节操作数大小,而%sil是一个8位寄存器。 short 是用于 x86-64 的 C ABI 中的 16 位类型。 (ISO C 要求 short 至少为 16 位。)

add 的操作数大小决定了内存中有多少字节被修改,即*v 的对象表示的大小。

如果*vshort,那么丢弃低字节的进位而不是让它传播到高字节将是一个错误,即使出于某种原因我们知道b' s 值很小。


sizeof(b) = 2 是个把戏/红鲱鱼:

在 C 规则中,比int 窄的类型作为+= 等运算符的操作数被提升为int,然后int 的加法结果被转换回目标类型。

所以*v += b 不在乎b*v 宽还是窄。 这就是为什么问题必须告诉你sizeof(b);因为您无法addb 指令中推断出来,并且它不必匹配*v 的类型。

在 x86-64 System V 和 Windows x64 中,仅有的 16 位整数类型是 shortunsigned short,所以 sizeof(b) == 2 告诉我们 bshortunsigned short

(那些 ABI 也有 CHAR_BIT = 8 即 1 字节 char,这对于具有字节可寻址内存的机器来说是正常的。)


uint8_tint16_t 这样的固定宽度类型是unsigned charshort 的类型定义,等等。我没有把它们算在内。

这个问题还让我们排除了无符号类型,我们无法从 asm.xml 中排除。无符号加法和 2 的补码加法是相同的二元运算。

【讨论】:

  • 我们还被告知 “v 和 b 都是有符号数据类型或指向有符号数据类型的指针。” 但总的来说,是的,无符号看起来是一样的.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-05
相关资源
最近更新 更多