obj文件解读

在编译c和c++文件的时候,每个c或cpp文件都会被编译器编译成obj(object)文件,所有的obj文件和资源文件经链接(Link)成为可执行文件,obj文件可称为目标文件或中间文件。

另外,obj文件只输出程序的相对地址,而exe文件是绝对地址

dumpbin工具介绍

dumpbin是在Windows平台下用于显示COFF格式文件信息的一个命令行工具。你可以使用DUMPBIN去显示COFF格式的文件信息,比如像vc编译器生成的目标文件(obj),可执行文件(exe)和动态链接库(DLLs)等。

此工具只能在命令行下使用。

语法格式:

dumpbin [options] files
  • 1

或者

dumpbin fiels [options]
  • 1

例如:

dumpbin main.obj /all
  • 1

或者

dumpbin main.obj /section:.bss
  • 1

另外,可用使用/out:filename选项将信息输出到文件中。如:

dumpbin main.obj /section:.data /out:new.txt
  • 1
obj文件组成

使用/summary选项,或者将不输入任何选项,将显示出每个段的基本信息(段名和大小)。

dumpbin main.obj /headers /out:head.txt
  • 1

如下所示,可以得到obj的所有节(SECTION)的描述结构,即节头:

FILE HEADER VALUES
             14C machine (x86)
             19B number of sections
        543BC5C0 time date stamp Mon Oct 13 20:29:52 2014
           14D18 file pointer to symbol table
             643 number of symbols
               0 size of optional header
               0 characteristics
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

当然,还有其他头的信息,太多了,这里就不一一列举。

各节的信息

使用下面的命令可用获得各节的基本信息。

dumpbin main.obj  /out:head.txt
  • 1

如下所示:

Summary

    14 .CRT$XCU
     E .bss
    A7 .data
  BB7C .debug$S
    6C .debug$T
   1C4 .drectve
   333 .rdata
   128 .rdata$r
     4 .rtc$IMZ
     4 .rtc$TMZ
    14 .sxdata
  20BD .text
    CE .text$x
   135 .text$yc
    B4 .text$yd
   13C .xdata$x
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

其中,左边是节的大小,右边是节名。

(.data)节

.data节用于存储已经初始化的静态(全局)变量

// 如果是数组比如

int Array1[10];

int Array2[10] = {13};

那么在.data里有Array2,Array1应该放在了符号表等到运行时才创建并分配内存。

如下main.cpp函数函数:

#include <iostream>
int a = 1;
int b = 2;
int main()
{
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

编译后生成main.obj文件,使用下述命令查看.data节信息:

dumpbin main.obj /section:.data
  • 1

输出如下:

SECTION HEADER #6B
   .data name
       0 physical address
       0 virtual address
       8 size of raw data
    9062 file pointer to raw data (00009062 to 00009069)
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
C0300040 flags
         Initialized Data
         4 byte align
         Read Write
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

其中: 1. size of raw data : 表明为其预留的空间 2. physical address : 物理地址 3. virtual adderss : 虚拟地址 4. Initialized Data : 初始化的数据 5. 4 byte align : 4字节对齐 6. Read Write : 可读、可写

另外,从size of raw data可以看出,预留来8Byte的空间,这是因为我们在函数中定义来两个初始化的int型全局变量。 再看下面的代码:

#include <iostream>
int a = 1;
int b = 2;
double c = 3;
int main()
{
    static int d = 4;
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

此时的输出为:

SECTION HEADER #6B
   .data name
        ...
       18 size of raw data
        ...
         8 byte align
         Read Write
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

注意:前面的数组是十六进制,18(十六进制) = 24(十进制)。

此时的预留空间变成来24字节,而我们只定义来两个初始化的int型全局变量,一个初始化的int型静态变量,一个初始化的double型全局变量,应该占用20个字节猜对。看下面的8 byte align,原来是因为double进行的8字节对齐。

再看下面的代码:

#include <iostream>
int a = 1;
char *p = "abc";
int main()
{
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

此时的输出为:

SECTION HEADER #6B
   .data name
        ...
       8 size of raw data
        ...
         8 byte align
         Read Write
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

这是因为,只预留来一个初始化的全局指针(32位程序中一个指针占4个字节),一个初始的int型全局变量的空间。而字符串”abc”是存在.rada段的。

(.bss)节

.bss 节用于存储未初始化的静态或全局变量

未定义未初始化的静态或全局变量时,输出如下所示:

SECTION HEADER #16E
    .bss name
       0 physical address
       0 virtual address
       2 size of raw data
       0 file pointer to raw data
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
C0100080 flags
         Uninitialized Data
         1 byte align
         Read Write
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

可见,默认预留来2Byte的空间Uninitialized Data表示未初始化的数据。// 我个人测试的时候并没有看到预留,如果没有符合条件的变量,那么直接就没有这个SECTION.

看下面的代码:

#include <iostream>
int a ;
int main()
{
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

此时的输出为:

SECTION HEADER #6B
   .bss name
        ...
       6 size of raw data
        ...
         4 byte align
         Read Write
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

多了一个未初始化的全局变量,所以预留的空间就多了4字节。

(.rdata)节

字符常量保存在.rdata中。

看下面的代码:

#include <iostream>
char *p = "abc";
int main()
{
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

此时,rdata的大小为337字节。

再看下面的代码:

#include <iostream>
char *p = "abcdefghi";
int main()
{
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

此时,rdata的大小为33D字节。

再看下面的代码:

#include <iostream>
int main()
{
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5

此时,rdata的大小为333字节。

“abc”字符串常量占四个字节 = 337 - 333; “abcdefghi”字符串常量占十个字节 = 33D - 333;

对于最初的代码,在.rdata节中查找abc可以找到下面的部份:

SECTION HEADER #17A
  .rdata name
       0 physical address
       0 virtual address
       4 size of raw data
   14797 file pointer to raw data (00014797 to 0001479A)
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
40301040 flags
         Initialized Data
         COMDAT; sym= "`string'" (??_C@_03FIKCJHKP@abc?$AA@)
         4 byte align
         Read Only
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

看的了abc吧。// 同时在data区也会有一个relocation到这个常量

(.text)节

.text 节用于存储程序代码。

看下面的代码:

#include <iostream>
int main()
{
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5

此时,text的大小为20B6字节。

再看下面的代码:

#include <iostream>
int main()
{
    int a = 1;
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

此时,text的大小为20BD字节,多了7个字节。

再看下面的代码:

#include <iostream>
int main()
{
    int a = 1;
    int b = 2;
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

此时,text的大小为20C4字节,又多了7个字节。

再看下面的代码:

#include <iostream>
int main()
{
    int a = 1;
    int b = 2;
    double c = 3;
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

此时,text的大小为20D1字节,又多了13个字节。


// 如果函数如下,则会有两个单独的.rdata出来存储里面的常量。一个存储OOOOO,一个存储XXXXX。

void TTS()
{

printf("OOOOO");

        printf("OOOOO");

    printf("XXXXX");

}

const修饰的量确切说叫只读量,不是常量。

可能在栈区,可能在全局区,看作用域以及有没有static修饰了,如果没有对其取地址的话,也可能被编译器优化为字面常量。

①static无论是全局变量还是局部变量都存储在全局/静态区域,在编译期就为其分配内存,在程序结束时释放,例如:val_a、val_d、val_h、val_i。

const全局变量存储在只读数据段,编译期最初将其保存在符号表中,第一次使用时为其分配内存,在程序结束时释放,例如:val_c;const局部变量存储在栈中,代码块结束时释放,例如:val_j。

③全局变量存储在全局/静态区域,在编译期为其分配内存,在程序结束时释放,例如:val_b、val_e。

④局部变量存储在中,代码块结束时释放,例如:val_h、val_i。

注:当全局变量和静态局部变量未赋初值时,系统自动置为0。


详细可参考:https://en.wikipedia.org/wiki/Object_file


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Noma是一家3D打印公司,他们提供的一些3D打印产品需要用到.obj格式的文件。如果你需要下载Noma的.obj文件,首先你需要去到Noma的官方网站。然后在搜索栏中输入你需要的.obj文件名称,并按下Enter键进行搜索。通常Noma会将自己提供的.obj文件放在一个独立的资源库中,你可以在该资源库中找到你需要的文件并进行下载。另外,你还可以在Github上查找Noma的开源项目,并在其中下载对应的.obj文件。但是,需要注意的是,Noma的.obj文件并不是免费的,你需要支付一定的费用才能够下载到该文件。另外,如果你需要下载的是Noma的定制化3D打印产品的.obj文件,你需要联系Noma并提供相关的定制化需求和付款信息,才能够获得下载权限。总之,你需要根据不同的情况来决定如何获取Noma的.obj文件。 ### 回答2: Noma是一个流行的外观系统的名称,其3D体系结构模型通常可以通过OBJ文件下载来获取。OBJ文件是3D模型文件格式的一种,通常用来保存三维几何形状的数据,以及材质、法线和颜色等相关信息。要下载Noma的OBJ文件,您可以很容易地在各种3D模型下载网站上搜索到它们,例如TurboSquid、CGTrader和Sketchfab等等。许多这些网站都提供免费的和付费的下载选项,所以您可以按照自己的需求选择合适的选项。 下载下来的OBJ文件可以在许多不同的3D软件上使用,例如Blender、Maya和3ds Max等等。在某些情况下,您还需要安装相应的3D插件来支持OBJ文件的导入和处理。一旦您成功下载了Noma的OBJ文件,您便可以在您的3D场景中利用它们来创建各种精美的外观效果,例如建筑、汽车、飞机、游戏角色等等。总的来说,Noma OBJ文件的下载和使用是一个相对简单的过程,只需要您有一些3D建模和渲染的基础知识和技能即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值