为什么我的 const 数组存储在堆栈而不是文本部分?
Why is my const array stored on the stack instead of the text section?
我正在实施一个加密算法(用于教育目的),我注意到一些奇怪的事情。部分算法使用 s-box 进行替换,所以我分配了 const
个数组用作查找 table,如下所示:
const unsigned char s0_lookup[4][4]={{1,0,3,2},
{3,2,1,0},
{0,2,1,3},
{3,1,3,2}};
const unsigned char s1_lookup[4][4]={{0,1,2,3},
{2,0,1,3},
{3,0,1,0},
{2,1,0,3}};
由于数组使用 const
限定符,我认为它们应该存储在文本区域而不是堆栈中。但是,如果我反汇编编译器的输出,我会看到:
0000000000000893 <s_des_sbox>:
893: 55 push %rbp
894: 48 89 e5 mov %rsp,%rbp
897: 48 89 7d c8 mov %rdi,-0x38(%rbp)
89b: c6 45 dd 00 movb [=11=]x0,-0x23(%rbp)
89f: c6 45 e0 01 movb [=11=]x1,-0x20(%rbp)
8a3: c6 45 e1 00 movb [=11=]x0,-0x1f(%rbp)
8a7: c6 45 e2 03 movb [=11=]x3,-0x1e(%rbp)
8ab: c6 45 e3 02 movb [=11=]x2,-0x1d(%rbp)
8af: c6 45 e4 03 movb [=11=]x3,-0x1c(%rbp)
8b3: c6 45 e5 02 movb [=11=]x2,-0x1b(%rbp)
8b7: c6 45 e6 01 movb [=11=]x1,-0x1a(%rbp)
8bb: c6 45 e7 00 movb [=11=]x0,-0x19(%rbp)
8bf: c6 45 e8 00 movb [=11=]x0,-0x18(%rbp)
8c3: c6 45 e9 02 movb [=11=]x2,-0x17(%rbp)
8c7: c6 45 ea 01 movb [=11=]x1,-0x16(%rbp)
8cb: c6 45 eb 03 movb [=11=]x3,-0x15(%rbp)
8cf: c6 45 ec 03 movb [=11=]x3,-0x14(%rbp)
8d3: c6 45 ed 01 movb [=11=]x1,-0x13(%rbp)
8d7: c6 45 ee 03 movb [=11=]x3,-0x12(%rbp)
8db: c6 45 ef 02 movb [=11=]x2,-0x11(%rbp)
8df: c6 45 f0 00 movb [=11=]x0,-0x10(%rbp)
8e3: c6 45 f1 01 movb [=11=]x1,-0xf(%rbp)
8e7: c6 45 f2 02 movb [=11=]x2,-0xe(%rbp)
8eb: c6 45 f3 03 movb [=11=]x3,-0xd(%rbp)
8ef: c6 45 f4 02 movb [=11=]x2,-0xc(%rbp)
8f3: c6 45 f5 00 movb [=11=]x0,-0xb(%rbp)
8f7: c6 45 f6 01 movb [=11=]x1,-0xa(%rbp)
8fb: c6 45 f7 03 movb [=11=]x3,-0x9(%rbp)
8ff: c6 45 f8 03 movb [=11=]x3,-0x8(%rbp)
903: c6 45 f9 00 movb [=11=]x0,-0x7(%rbp)
907: c6 45 fa 01 movb [=11=]x1,-0x6(%rbp)
90b: c6 45 fb 00 movb [=11=]x0,-0x5(%rbp)
90f: c6 45 fc 02 movb [=11=]x2,-0x4(%rbp)
913: c6 45 fd 01 movb [=11=]x1,-0x3(%rbp)
917: c6 45 fe 00 movb [=11=]x0,-0x2(%rbp)
91b: c6 45 ff 03 movb [=11=]x3,-0x1(%rbp)
代码正在移动文字常量以填充堆栈上的空数组!当整个数组可以简单地存储为常量时,这对我来说似乎非常低效。为什么我的代码会这样?
因为它是在函数中声明的并且是非静态的,所以它通常分配在堆栈上。由于 C 允许递归,每次调用您的函数都将获得数组的新副本,并在 运行 时填充。
要使其在构建时仅初始化一次,您应该将其设为静态:
static const unsigned char s0_lookup[4][4]={{1,0,3,2},
{3,2,1,0},
{0,2,1,3},
{3,1,3,2}};
因为它被声明为 const,优化可以利用 as-if 规则并按照您编写的方式对其进行编译 static const ...
但没有任何强制编译器这样做。
我正在实施一个加密算法(用于教育目的),我注意到一些奇怪的事情。部分算法使用 s-box 进行替换,所以我分配了 const
个数组用作查找 table,如下所示:
const unsigned char s0_lookup[4][4]={{1,0,3,2},
{3,2,1,0},
{0,2,1,3},
{3,1,3,2}};
const unsigned char s1_lookup[4][4]={{0,1,2,3},
{2,0,1,3},
{3,0,1,0},
{2,1,0,3}};
由于数组使用 const
限定符,我认为它们应该存储在文本区域而不是堆栈中。但是,如果我反汇编编译器的输出,我会看到:
0000000000000893 <s_des_sbox>:
893: 55 push %rbp
894: 48 89 e5 mov %rsp,%rbp
897: 48 89 7d c8 mov %rdi,-0x38(%rbp)
89b: c6 45 dd 00 movb [=11=]x0,-0x23(%rbp)
89f: c6 45 e0 01 movb [=11=]x1,-0x20(%rbp)
8a3: c6 45 e1 00 movb [=11=]x0,-0x1f(%rbp)
8a7: c6 45 e2 03 movb [=11=]x3,-0x1e(%rbp)
8ab: c6 45 e3 02 movb [=11=]x2,-0x1d(%rbp)
8af: c6 45 e4 03 movb [=11=]x3,-0x1c(%rbp)
8b3: c6 45 e5 02 movb [=11=]x2,-0x1b(%rbp)
8b7: c6 45 e6 01 movb [=11=]x1,-0x1a(%rbp)
8bb: c6 45 e7 00 movb [=11=]x0,-0x19(%rbp)
8bf: c6 45 e8 00 movb [=11=]x0,-0x18(%rbp)
8c3: c6 45 e9 02 movb [=11=]x2,-0x17(%rbp)
8c7: c6 45 ea 01 movb [=11=]x1,-0x16(%rbp)
8cb: c6 45 eb 03 movb [=11=]x3,-0x15(%rbp)
8cf: c6 45 ec 03 movb [=11=]x3,-0x14(%rbp)
8d3: c6 45 ed 01 movb [=11=]x1,-0x13(%rbp)
8d7: c6 45 ee 03 movb [=11=]x3,-0x12(%rbp)
8db: c6 45 ef 02 movb [=11=]x2,-0x11(%rbp)
8df: c6 45 f0 00 movb [=11=]x0,-0x10(%rbp)
8e3: c6 45 f1 01 movb [=11=]x1,-0xf(%rbp)
8e7: c6 45 f2 02 movb [=11=]x2,-0xe(%rbp)
8eb: c6 45 f3 03 movb [=11=]x3,-0xd(%rbp)
8ef: c6 45 f4 02 movb [=11=]x2,-0xc(%rbp)
8f3: c6 45 f5 00 movb [=11=]x0,-0xb(%rbp)
8f7: c6 45 f6 01 movb [=11=]x1,-0xa(%rbp)
8fb: c6 45 f7 03 movb [=11=]x3,-0x9(%rbp)
8ff: c6 45 f8 03 movb [=11=]x3,-0x8(%rbp)
903: c6 45 f9 00 movb [=11=]x0,-0x7(%rbp)
907: c6 45 fa 01 movb [=11=]x1,-0x6(%rbp)
90b: c6 45 fb 00 movb [=11=]x0,-0x5(%rbp)
90f: c6 45 fc 02 movb [=11=]x2,-0x4(%rbp)
913: c6 45 fd 01 movb [=11=]x1,-0x3(%rbp)
917: c6 45 fe 00 movb [=11=]x0,-0x2(%rbp)
91b: c6 45 ff 03 movb [=11=]x3,-0x1(%rbp)
代码正在移动文字常量以填充堆栈上的空数组!当整个数组可以简单地存储为常量时,这对我来说似乎非常低效。为什么我的代码会这样?
因为它是在函数中声明的并且是非静态的,所以它通常分配在堆栈上。由于 C 允许递归,每次调用您的函数都将获得数组的新副本,并在 运行 时填充。
要使其在构建时仅初始化一次,您应该将其设为静态:
static const unsigned char s0_lookup[4][4]={{1,0,3,2},
{3,2,1,0},
{0,2,1,3},
{3,1,3,2}};
因为它被声明为 const,优化可以利用 as-if 规则并按照您编写的方式对其进行编译 static const ...
但没有任何强制编译器这样做。