汇编程序与C程序的大小几乎相同

Sim*_*mon 0 c windows assembly executable filesize

例如:我创建了一个简单的C程序,打印"Hello,World",编译它并创建了一个大小为39.8Kb的可执行文件.

按照这个问题,我能够创建等效的但是用汇编写的,这个程序的大小是39.6Kb.

这让我感到非常惊讶,因为我期望汇编程序比C程序小.正如问题所示,它使用了C头和gcc编译器.这会使装配程序更大还是它们大致相同的大小是正常的?


使用strip命令我减少了两个文件.这删除了调试代码,现在两者都有非常相似的文件大小.两者都是18.5Kb.

test.c的:

old*_*mer 5

如果您的手写代码与编译函数相同,那么确定它们的大小相似,它们正在做同样的事情,如果您可以与编译器竞争,那么您将是相同或类似的.

现在你的文件大小表明你在一起看错了什么.您在调用二进制文件时正在查看的文件中包含大量其他内容.您想在此上下文中比较苹果和苹果,然后比较函数的大小,机器代码,而不是包含函数的容器的大小以及调试信息加字符串以及许多其他内容.

您的实验存在缺陷,但结果非常松散地表明预期结果.但是,如果您以相同的方式生成代码.这种可能性很小,所以除非你以同样的方式生成代码,否则你不应该期待类似的结果.

采取这个简单的功能

unsigned int fun ( unsigned int a, unsigned int b)
{
    return(a+b+1);
}
Run Code Online (Sandbox Code Playgroud)

相同的编译器产生了这个:

00000000 <fun>:
   0:   e52db004    push    {r11}       ; (str r11, [sp, #-4]!)
   4:   e28db000    add r11, sp, #0
   8:   e24dd00c    sub sp, sp, #12
   c:   e50b0008    str r0, [r11, #-8]
  10:   e50b100c    str r1, [r11, #-12]
  14:   e51b2008    ldr r2, [r11, #-8]
  18:   e51b300c    ldr r3, [r11, #-12]
  1c:   e0823003    add r3, r2, r3
  20:   e2833001    add r3, r3, #1
  24:   e1a00003    mov r0, r3
  28:   e28bd000    add sp, r11, #0
  2c:   e49db004    pop {r11}       ; (ldr r11, [sp], #4)
  30:   e12fff1e    bx  lr
Run Code Online (Sandbox Code Playgroud)

还有这个

00000000 <fun>:
   0:   e2811001    add r1, r1, #1
   4:   e0810000    add r0, r1, r0
   8:   e12fff1e    bx  lr
Run Code Online (Sandbox Code Playgroud)

因为设置不同.13指令vs 3,超过4倍.

人类可能直接从C生成这个,没什么特别的

add r0,r0,r1
add r0,r0,#1
bx lr
Run Code Online (Sandbox Code Playgroud)

如果你在技术上必须在将该总和添加到a之前将其添加到b,则不确定操作顺序.或者如果它无关紧要.我从左到右,编译器从右到左.

所以你可以说编译器和我的程序集产生了相同数量的二进制字节,或者你可以说编译器产生了超过4倍的东西.

采取上述内容并将其扩展为一个有用的实际程序.

练习给读者(OP,请不要破坏它)以弄清楚为什么编译器可以生成两个不同大小的正确解决方案.

编辑

所提到的.exe,elf和其他"二进制"格式可以包含调试信息,ascii字符串包含用于漂亮调试屏幕的函数/标签的名称.哪些是"二进制"的一部分,因为它们是行李的一部分,但不是机器代码,也不是执行该程序时使用的数据,至少不是我提到的东西.您可以在不更改程序所需的机器代码和数据的情况下,使用编译器设置来操纵.exe或其他文件格式的大小,因此相同的编译器 - 汇编程序 - 链接器或汇编程序 - 链接程序路径可以使某些二进制文件具有某种意义.包含或不包含此额外行李的字数大于或小于.这是理解文件大小的一部分,为什么即使你的hello world程序大小不同,整个文件也可能大小相同,如果一个长10个字节但.exe是40K那么10个字节就在噪声.但是,如果我理解你的问题,你知道如何比较编译和手写C之间的10个字节.

还要注意编译器是由人类制作的,因此它们产生的输出与至少那些人类可以产生的输出相当,其他人类可以做得更好,许多人会做得更糟,这取决于你对更好和更差的定义.


RbM*_*bMm 5

大小 39+ Kb 绝对与使用的编译器和语言(c/c++asm)不同的优化、调试信息等无关- 可以更改这个小代码的大小,比如 1000 字节。但不是更多。i 用于测试构建下一个程序

#include <Windows.h>
#include <stdio.h>
void ep(void*)
{
    ExitProcess(printf("Hello, World"));
}
Run Code Online (Sandbox Code Playgroud)

链接器选项:

/INCREMENTAL:NO /NOLOGO /MANIFEST:NO /NODEFAULTLIB 
/SUBSYSTEM:CONSOLE /OPT:REF /OPT:ICF /LTCG /ENTRY:"ep" /MACHINE:X64 kernel32.lib msvcrt.lib
Run Code Online (Sandbox Code Playgroud)

并为 x86/x64 获得大小为 2560 字节的 exe。

在什么不同?in/NODEFAULTLIB和我的版本msvcrt.lib- 这是纯导入库。

您使用静态链接的 c 运行时提供的其余 35kb+ 大小。即使您在 asm 上编写程序 - 您也需要使用一些 lib 来链接到printf. 和您的库包含一些与您的代码静态链接的代码。在这段代码中,这 35kb。

任务不是 c++ vs asm - 这里没有什么不同。任务正在使用 c-runtime 或未使用