微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c – GCC / g cout <<与printf()

>为什么printf(“hello world”)最终使用汇编代码中的更多cpu指令(不考虑使用的标准库)而不是cout<< “你好,世界”?
对于C,我们有:
movl    $.LC0,%esi
movl    $_ZSt4cout,%edi
call    _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc

对于C:

movl    $.LC0,%eax
movq    %rax,%rdi
movl    $0,%eax
call    printf

> C代码中的第2行和来自C代码的第2,3行是什么?

我正在使用gcc 4.5.2版

解决方法

对于Linux x86_64上的64位gcc -O3(4.5.0),它读取:cout<< “你好,世界”
movl    $11,%edx         ; String length in EDX
movl    $.LC0,%esi       ; String pointer in ESI
movl    $_ZSt4cout,%edi  ; load virtual table entry of "cout" for "ostream"
call    _ZSt16__ostream_insertIcSt11char_traits...basic_ostreamIT_T0_ES6_PKS3_l

并且,对于printf(“Hello World”)

movl    $.LC0,%edi       ; String pointer to EDI
xorl    %eax,%eax        ; clear EAX (maybe flag for printf=>no stack arguments)
call    printf

这意味着,你的序列完全取决于任何具体的
编译器实现,其版本和可能的编译器选项.
您的编辑状态,您使用gcc 4.5.2(这是相当新的).
似乎4.5.2引入了额外的64位寄存器
这个顺序无论出于什么原因它将64位RAX保存到RDI
在把它归零之前 – 这绝对没有意义(至少对我而言).

更有趣的是:3个参数调用序列(g -O1 -S source.cpp):

void c_proc()
{
 printf("%s %s %s","Hello","World","!") ;
}

 void cpp_proc()
{
 std::cout << "Hello " << "World " << "!";
}

导致(c_proc):

movl    $.LC0,%ecx
movl    $.LC1,%edx
movl    $.LC2,%esi
movl    $.LC3,%edi
movl    $0,%eax
call    printf

.LCx是字符串,不涉及堆栈指针!

对于cpp_proc:

movl    $6,%edx
movl    $.LC4,%edi
call    _ZSt16__ostream_insertIcSt11char_traits...basic_ostreamIT_T0_ES6_PKS3_l
movl    $6,%edx
movl    $.LC5,%edi
call    _ZSt16__ostream_insertIcSt11char_traits...basic_ostreamIT_T0_ES6_PKS3_l
movl    $1,%edx
movl    $.LC0,%edi
call    _ZSt16__ostream_insertIcSt11char_traits...basic_ostreamIT_T0_ES6_PKS3_l

你现在看到这是什么.

问候

RBO

原文地址:https://www.jb51.cc/c/118800.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐