本文介绍了在gcc、g++中生成ASM代码需要什么的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了缩小我的问题范围,让我描述一下我的假设和我所做的实验......

To narrow down my question, let me describe my assumption and the experiment that I did...

我的假设: 用汇编语言编写的代码将比其 C/C++ 对应的代码运行得快得多,而且可执行文件的大小也比从 C/C++ 代码生成的要小得多.

My assumption: A code written in assembly language will run much faster than its C/C++ counterpart and also the executable size to be much smaller than that generated from C/C++ code.

实验:我在bin2dec.c中写了下面的程序

The experiment: I wrote the below program in to bin2dec.c

#include <stdio.h>

int main()
{
    long int binary, decimal, reminder, exp;
    int i, j;

    for(i=0; i<10000; i++)
    {
        for(j=0; j<1000; j++)
        {
            binary = 11000101;

            exp = 1;
            decimal = 0;

            while(binary != 0)
            {
                reminder = binary % 10;
                binary = binary / 10;
                decimal = decimal + reminder * exp;
                exp *= 2;
            }
        }
    }
    return 0;
}

然后为其生成ASM代码gcc -S bin2dec.c -o bin2dec.s

Then generated the ASM code for it gcc -S bin2dec.c -o bin2dec.s

之后我编译了两个文件如下

After that I compiled both the files as below

gcc bin2dec.c -o bin2dec_c
gcc bin2dec.s -o bin2dec_s

测试 1:找出两个文件的一些内部细节

Test 1: Found out some internal details of both the files

[guest@localhost ASM]$ size bin2dec_c bin2dec_s
   text    data     bss     dec     hex filename
    951     252       4    1207     4b7 bin2dec_c
    951     252       4    1207     4b7 bin2dec_s

结果:两者完全相同...

Result: Both are exactly same...

测试 2:执行文件并计算所用时间

Test 2: Executed the files and calculated the time taken

[guest@localhost ASM]$ time ./bin2dec_c
real    0m1.724s
user    0m1.675s
sys     0m0.002s

[guest@localhost ASM]$ time ./bin2dec_s
real    0m1.721s
user    0m1.676s
sys     0m0.001s

结果:两者相同.有时,从 ASM 生成的可执行文件运行速度较慢 :-(

Result: Both are same. Some time the executable generated from ASM ran slower :-(

所以问题是,我的假设是否错误?如果不是,我犯了什么错误使可执行文件 bin2dec_c 和 bin2dec_s 以相同的速度运行?有没有更好的方法从 C/C++ 程序中获取 ASM 代码,或者我应该从头开始重写 ASM 中的所有逻辑以获得速度和程序大小的优势?

So the question is, whether my assumptions were wrong?If not, what mistake I did so that both the executables bin2dec_c and bin2dec_s ran at the same speed?Is there any better way to get ASM code from a C/C++ program or I should rewrite all the logic from the scratch in ASM to gain the advantage of speed and program size?

推荐答案

这是一个古老的传统(在 1970 年代早期的 Unix 系统上,机器很小,生成一些汇编文件比较简单),还有一些编译器可以直接生成目标文件或机器码;可能是最近版本的 Clang/LLVMTinyCC (仅适用于 C:编译时间快,但执行速度非常慢!)也许是 IBM 的一些专有 XLC 编译器,而 GCC 社区中的一些人正在考虑这个问题(尤其是 GCCJIT).

It is an old tradition (in the 1970s on early Unix systems, the machine was so small that it was simpler to generate some assembler file), and some compilers can generate directly object files or machine code; probably some recent version of Clang/LLVM, or TinyCC (for C only: fast compilation time, but very slow executable!) perhaps some proprietary XLC compiler from IBM, and some people amongst the GCC community are thinking about that (notably for GCCJIT).

但是,编译器开发人员通常更容易生成汇编文件.而且由于大部分编译器工作都发生在 优化 通道中(正在转换一些内部表示 在编译器中),失去几毫秒来启动汇编器并不是很重要.

However, generating an assembler file is often easier for compiler developers. And since most of the compiler work happens in optimization passes (which are transforming some internal representations in the compiler), losing a few milliseconds to start the assembler is not very important.

使用 GCC,使用 gcc -timegcc - 进行编译ftime-report(当然还有你常用的优化标志,例如 -O2)来了解编译器将时间花在哪里.它永远不会在汇编程序中......

With GCC, compile with gcc -time and gcc -ftime-report (and of course your usual optimization flags, e.g. -O2) to understand where the compiler spends its time. It is never in the assembler...

您有时可能会发现查看生成的汇编文件很有用.使用 g++ -O2 -Wall -S -fverbose-asm -std=c++11 foo.cc 编译您的 foo.cc C++11 文件,然后查看(使用一些编辑器或寻呼机)到生成的 foo.s 汇编文件中.

You might sometimes find useful to look into the generated assembler file. Compile your foo.cc C++11 file with g++ -O2 -Wall -S -fverbose-asm -std=c++11 foo.cc then look (with some editor or pager) into the generated foo.s assembler file.

您甚至可以使用 g++ -fdump-tree-all -O2 进行编译,并从 GCC 解释编译器对你的代码做了哪些转换.

You could even compile with g++ -fdump-tree-all -O2 and get hundreds of compiler dump files from GCC explaining what transformations the compiler did on your code.

顺便说一句,当今的(超标量、流水线)处理器(台式机、笔记本电脑、平板电脑、服务器中的处理器)非常复杂,以至于实际上编译器可以比人类程序员进行更好的优化.所以实际上由一个优化编译器从一些实际大小的 C 代码(例如几百行的 C 源文件)生成的汇编代码> 通常比经过试验的汇编程序人类程序员在几周内编写的代码要快(不到一千行汇编程序行).换句话说,您的假设(用汇编程序人工编写的代码比用 C 语言编写并由良好的优化编译器编译的代码更快/更好)错误 在实践中.

BTW today's (superscalar, pipelined) processors (the ones in your desktop, your laptop, your tablet, your server) are so complex that in practice a compiler can optimize better than a human programmer. So practically speaking the assembler code produced by an optimizing compiler from some realistically sized C code (e.g. a C source file of a few hundred lines) is often faster than what an experimented assembler human programmer can code in a few weeks (less than a thousand assembler lines). In other words your assumption (that code human-written in assembler is faster/better than code human-written in C and compiled by a good optimizing compiler) is wrong in practice.

另请阅读停止问题赖斯定理.优化编译器或静态程序分析器可以实现的功能存在内在限制.

Read also about the halting problem and Rice's theorem. There is a intrinsic limitation in what optimizing compilers or static program analyzers can achieve.

这篇关于在gcc、g++中生成ASM代码需要什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-23 07:03