【问题标题】:const variables in local and global scope in assembly程序集中局部和全局范围内的 const 变量
【发布时间】:2020-08-29 05:28:28
【问题描述】:

我在Compiler Exporer 中编译了以下C 代码,看看它如何处理const 关键字:

int a=1;
const b=2;
int func () {
    int c=3;
    const int d=4;
}

        .section        .data
a:
        .long   1
        .section        .rodata
b:
        .long   2
func:
        pushq   %rbp
        movq    %rsp, %rbp
        movl    $3, -4(%rbp)
        movl    $4, -8(%rbp)
        nop     # also, why does it add a nop here?
        popq    %rbp
        ret

据我所知,对于在函数外部定义的变量(文件的全局变量),它会在顶部添加一个标签。但是,如果它是const 变量,那么顶部的变量将被放置在只读部分中。然后我的问题是针对以下局部变量:

const int d=4;

它的“常数”是如何管理的,因为它只是堆栈上的一个值,不能随意修改堆栈上的任何值吗?或者,在汇编中,不存在常量局部变量之类的东西,而这只是编译器强制执行的概念?

【问题讨论】:

标签: c assembly gcc x86


【解决方案1】:

如果您不获取地址,则无需在任何地方的数据存储器中保留const 本地。 asm 等效项是 NASM d equ 4 或 GAS d = 4,因此您可以在需要时立即使用它。

与碰巧不会被修改的非const int 相同:是的,局部变量的常量纯粹是编译器强制执行以帮助您捕获错误的编译时事物。

【讨论】:

  • 我明白了。所以要做这样的事情:d = 5; mov $d, %r9 ?
  • 是的。当然d=5 在全局范围内实际上更像static const int d = 5;(同样会优化掉和内联),因为 asm 并没有真正的范围。 (除非您在函数后手动取消设置 asm 符号)
  • 我明白了。是否有取消设置符号的说明?或者这只是通过破坏内存位置来完成的?
  • @David542:当然不是指令,这没有任何意义。可能有一个指令,但事实证明 GAS 没有.undef.unset,只有.set。这就说得通了; asm 通常允许引用稍后定义的符号,这与 C 或 C 宏预处理器不同。
  • 感谢您的澄清。 static const 上的一个问题,变量在哪里初始化(以便气体可以引用它?),它是第一次被引用吗?我问是因为当我在gdb 中检查东西时,我没有看到d=5 指令,所以我猜它是汇编程序内部的或其他东西(或者我可能只是遗漏了一些东西)。
【解决方案2】:

试试吧。

int fun ( void )
{
    const int d=4;
    return(d);
}

00000000 <fun>:
   0:   e3a00004    mov r0, #4
   4:   e12fff1e    bx  lr



int fun ( void )
{
    const int d=4;
    return(d);
}
int fun1( void )
{
    int d=4;
    d=5;
    return(d);
}
int fun2 ( void )
{
    const int d=4;
    d=5;
    return(d);
}

so.c: In function ‘fun2’:
so.c:16:6: error: assignment of read-only variable ‘d’


int fun ( void )
{
    const int d=4;
    return(d);
}
int fun1( void )
{
    int d=4;
    d=5;
    return(d);
}

00000000 <fun>:
   0:   e3a00004    mov r0, #4
   4:   e12fff1e    bx  lr

00000008 <fun1>:
   8:   e3a00005    mov r0, #5
   c:   e12fff1e    bx  lr

全局变量是全局的,在某个段中获得内存分配,局部变量是局部变量,除非声明为静态(局部全局变量),它们位于堆栈或寄存器中。 const 只是向编译器表明它可以基于变量是只读而不是读/写的假设生成代码。如果您尝试写入只读声明的变量,更好的编译器会抱怨。所以 const int 和 int 的区别是 read/only vs read/write。

【讨论】:

  • 在向初学者解释内容时包含编译命令/选项很重要。他们通常没有意识到启用优化的重要性。此外,您可以将 godbolt.org 上的示例与 ARM gcc 链接起来。
猜你喜欢
  • 2017-03-05
  • 2023-03-29
  • 2016-11-13
  • 1970-01-01
  • 1970-01-01
  • 2013-07-13
  • 2013-12-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多