首页 > 解决方案 > 我应该如何推断 x86-64 机器上 addb 指令的 C 数据类型?

问题描述

我有以下 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*。为什么不能短*?

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

标签: cassemblytypesx86-64

解决方案


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

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

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

如果*vshort,即使由于某种原因我们知道b的值很小,从低字节丢弃进位而不是让它传播到高字节也是错误的。


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

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

所以*v += b不关心b是宽还是窄于*v 这就是为什么这个问题必须告诉你sizeof(b);因为您无法从指令中推断出这一点,addb并且它不必与*v.

在 x86-64 System V 和 Windows x64 中,唯一的 16 位整数类型是shortand unsigned short,所以sizeof(b) == 2告诉我们bshortor unsigned short

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


固定宽度类型,例如uint8_tand是andint16_t的 typedef ,等等。我没有为此计算他们。unsigned charshort

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


推荐阅读