繁体   English   中英

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

[英]mapping from (Assembly) instruction sequences to C code

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

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位。 但是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的知识,因此请将这些定义用于您的测试代码和对此作业的答案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM