从(汇编)指令序列映射到 C 代码



我的教科书中有一个练习:

int comp(data_t a, data_t b) {
return a COMP b;
}

显示了参数 A 和 B 之间的一般比较,我们可以在其中设置 参数的数据类型,通过使用 typedef 声明声明data_t,以及 我们可以通过使用 #define 声明定义 COMP 来设置比较。假设 a 在 %edx 中,b 在 %eax 中。对于以下每个指令序列,确定data_t哪些数据类型(可以有多个正确答案;您应该将它们全部列出。

cmpl %eax, %edx
setl %al

教科书上的答案是:

后缀"l"和寄存器标识符表示 32 位操作数,而比较是针对二进制补码"<"。我们可以推断data_t一定是 int。

所以我的问题是:既然它要求列出所有可能的答案,为什么data_t不能也是 32 位的"long int"和指针?

对于您非常具体的问题,非常具体的答案是因为 long 没有固定的大小定义。 当第一个 32 位 x86 处理器问世并开始 16 位到 32 位转换时,对于许多编译器 int 从 16 位更改为 32 位。 但长 int 保持在 32 位。 这种情况一直持续到 64 位 x86 处理器问世,并且 a/一些流行的编译器将 long 更改为 64 位,int 保持 32 位。

但是int或long的定义是编译器作者的选择,语言规范中使用术语"实现定义"来涵盖这一点。 因此,很可能同一编译器的一个编译器或编译器版本解释的长度为 32 位,而另一个编译器或同一编译器的版本解释的长度为 64 位。 这就是stdint.h的来源,它有点黑客,但基于C语言的年龄和历史以及许多编译器,他们没有太多选择。

现在,如果您进一步示例编译器输出,您可能会/会发现一些编译器使用较大的寄存器 eax/rax 并避免 al/bl ah/bl 操作,这在一定程度上与微编码和性能有关。 所以cmpl和eax/edx告诉你故事的开始,直接阅读你的汇编程序文档的汇编语言(汇编语言是由汇编程序,工具定义的,而不是芯片/逻辑设计师,尽管它们通常大多类似于芯片/IP供应商的文档(。 然后允许一些复制者可以对较小的变量(当然不是更大的变量(使用相同的特定指令的可能性。

但是此程序集与提供的 C 代码不匹配,除非 int 的定义是 8 位。 教科书暗示 int 的定义是 32 位。 所以这是一个可怕且非常破碎的例子。 如果教科书的其余部分是这样的,祝你好运。 无论如何,x86 是错误的第一个指令集,永远不应该用于教授这种主题。 许多/大多数其他人会更好地为您服务。 我相信你可能别无选择,所以你的任务要困难得多。

您可以/应该做的是获取该代码,获取您拥有并为data_t和 COMP 提供定义的一个或多个编译器,看看您得到了什么。 C 代码中的_t意味着 stdint.h 的知识,因此请将这些定义用于您的测试代码和您对家庭作业的回答。

相关内容

  • 没有找到相关文章

最新更新