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

时间:2018-08-22 01:55:41

标签: c assembly instruction-set machine-instruction

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

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'和指针?

1 个答案:

答案 0 :(得分:1)

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

但是对int或long长度的定义是编译器作者的选择,在语言规范中使用术语“实现定义”来覆盖这一点。因此,对于同一目标,一个编译器或同一编译器的编译器版本很可能解释为32位长,而同一版本的另一编译器或同一版本的解释器则最长解释为64位。这是stdint.h的来源,虽然有点破烂,但基于C语言的年代和历史以及许多编译器,他们没有太多选择。

现在,如果您进一步举例说明编译器输出,则可能会/会发现某些编译器使用较大的寄存器eax / rax并避免执行al / bl ah / bl操作,这在一定程度上与微编码和性能有关。因此,cmpl和eax / edx告诉您故事的开始,请直接阅读汇编器文档中的汇编语言(汇编语言是由汇编器,工具而非芯片/逻辑设计器定义的,尽管它们通常通常类似于芯片/ ip供应商文档)。然后考虑到某些copmiler可以将相同的特定指令用于较小的变量(但当然不能较大)的可能性。

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

您可以/应该做的是获取该代码,获取您拥有的一个或多个提供了data_t和COMP定义的编译器,然后看看您得到了什么。 C代码中的_t表示stdint.h的知识,因此请使用这些定义作为您的测试代码和对此作业的答案。