将C++转换为C
Convert C++ to C
假设我把一个c++
程序带到哪里,并将其编译成一个程序集(.S
)文件。
然后,我将该汇编文件"disassembly"到C
中,该代码是否可以在不同的平台上重新编译?
我问这个问题的原因是,我试图开发的平台没有c++
编译器,而它确实有c
编译器。
是的,按照您描述的方式,这确实是可能的。不,它不会移植到任何CPU体系结构、操作系统和编译器三元组,除了你的。
让我们看看原因。拿一些基本的C++代码。。。
#include <iostream>
int main()
{
std::cout << "Hello, world!n";
return 0;
}
让我们在x86-64 Linux上使用g++
将其转换为汇编程序(我特意打开了优化,并丢弃了调试符号)。。。
$ g++ -o test.s -O3 -S test.cpp
结果是…
.file "test.cpp"
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "Hello, world!n"
.section .text.unlikely,"ax",@progbits
.LCOLDB1:
.section .text.startup,"ax",@progbits
.LHOTB1:
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB1027:
.cfi_startproc
subq $8, %rsp
.cfi_def_cfa_offset 16
movl $.LC0, %esi
movl $_ZSt4cout, %edi
call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
xorl %eax, %eax
addq $8, %rsp
.cfi_def_cfa_offset 8
ret
.cfi_endproc
.LFE1027:
.size main, .-main
.section .text.unlikely
.LCOLDE1:
.section .text.startup
.LHOTE1:
.section .text.unlikely
.LCOLDB2:
.section .text.startup
.LHOTB2:
.p2align 4,,15
.type _GLOBAL__sub_I_main, @function
_GLOBAL__sub_I_main:
.LFB1032:
.cfi_startproc
subq $8, %rsp
.cfi_def_cfa_offset 16
movl $_ZStL8__ioinit, %edi
call _ZNSt8ios_base4InitC1Ev
movl $__dso_handle, %edx
movl $_ZStL8__ioinit, %esi
movl $_ZNSt8ios_base4InitD1Ev, %edi
addq $8, %rsp
.cfi_def_cfa_offset 8
jmp __cxa_atexit
.cfi_endproc
.LFE1032:
.size _GLOBAL__sub_I_main, .-_GLOBAL__sub_I_main
.section .text.unlikely
.LCOLDE2:
.section .text.startup
.LHOTE2:
.section .init_array,"aw"
.align 8
.quad _GLOBAL__sub_I_main
.local _ZStL8__ioinit
.comm _ZStL8__ioinit,1,1
.hidden __dso_handle
.ident "GCC: (GNU) 5.3.1 20151207 (Red Hat 5.3.1-2)"
.section .note.GNU-stack,"",@progbits
这种混乱就是我们为异常处理、模板和名称空间付出的代价。让我们手动将其分解为C,丢弃异常处理表以获得更清晰的视图。。。
/* std::ostream */
typedef struct
{
/* ... */
} _ZSo;
/* extern operator<<(std::basic_ostream&, const char*); */
extern _ZStlsIst11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc();
/* namespace std { extern ostream cout; } */
extern _ZSo _ZSt4cout;
/* Our string, of course! */
static const char* LC0 = "Hello, world!n";
int main()
{
_ZStlsIst11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc(&_ZSt4cout, LC0);
return 0;
}
看起来不可读,但可移植,对吧?现在是这样。但是,这个代码不起作用!您还需要用struct
的术语定义_ZSo
(std::ostream
),更不用说包括所有的异常处理内容了。
一旦你开始使用try
/throw
/catch
,事情就变得几乎不可能便携。我的意思是,__cxa_allocate_exception
或__cxa_throw
绝对不可能是便携的!解决这一问题的唯一方法是重写所有程序(包括您使用的所有库,甚至是标准库!),以使用较慢的setjmp
/longjmp
方法处理异常,而不是零成本异常处理。
最后,但并非最不重要的是,即使是在最简单的输入下,非人类反汇编程序也很可能无法正确完成这项工作。请记住,在最底层的东西(也称为机器代码和汇编语言)中,没有类型的概念。例如,你永远不可能知道寄存器是有符号整数、无符号整数,还是基本上是其他的。编译器还可以随意使用堆栈指针,从而使作业恶化。
编译结束后,编译器不希望将来进行任何反汇编,会删除所有这些宝贵的信息,因为在运行时通常不需要这些信息。在大多数情况下,如果可能的话,拆卸真的不值得,而且很可能你正在寻求不同的解决方案。从中等偏上的语言翻译成中等偏下的语言将这一点发挥到了极致,并接近了可以翻译成其他语言的极限。
- 防止主数据类型C++的隐式转换
- 模板参数替换失败,并且未完成隐式转换
- 努力将整数转换为链表。不知道我在这里做错了什么
- HEX值到wchar_t字符(UTF-8)的转换
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将 Qvector<uint8_t> 转换为 QString
- 如何在cuSparse中使用cusparseXcoo2csr从coo转换为csc
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 在c++中使用nlohmann从类到json的转换
- 从"int*"强制转换为"unsigned int"会丢失精度错误
- 将Integer转换为4字节的unsined字符矢量(按大端字节顺序)
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 如何使用OpenCV将RBG图像转换为HSV,并将H、S和V值保存为C++中的3个独立图像
- 复制列表初始化的隐式转换的等级是多少
- 正在将指针转换为范围
- 如何防止 c++ 在从浮点型转换为双精度型(不适用于 IO)时添加额外的小数?
- 将"打开的CV图像"中的"颜色"转换为整数格式
- 是否可以从int转换为enum类类型
- 了解 GLM- openGL 中的相机转换
- 将无符号char*转换为std::istream*C++