首页 > 解决方案 > 如果 gcc -O3 没有“volatile”,为什么一个简单的 C“hello world”程序不起作用?

问题描述

我有以下 C 程序

int main() {
char string[] = "Hello, world.\r\n";
__asm__ volatile ("syscall;" :: "a" (1), "D" (0), "S" ((unsigned long) string), "d" (sizeof(string) - 1)); }

我想用 x86 64 位在 Linux 下运行。我用 0 作为 fd 参数调用“写入”的系统调用,因为这是标准输出。

如果我在 gcc 下使用 -O3 编译,它不起作用。查看汇编代码

    .file   "test_for_o3.c"
.text
.section    .text.startup,"ax",@progbits
.p2align 4,,15
.globl  main
.type   main, @function
main:
.LFB0:
    .cfi_startproc
    subq    $40, %rsp
    .cfi_def_cfa_offset 48
    xorl    %edi, %edi
    movl    $15, %edx
    movq    %fs:40, %rax
    movq    %rax, 24(%rsp)
    xorl    %eax, %eax
    movq    %rsp, %rsi
    movl    $1, %eax
#APP
# 5 "test_for_o3.c" 1
    syscall;
# 0 "" 2
#NO_APP
    movq    24(%rsp), %rcx
    xorq    %fs:40, %rcx
    jne .L5
    xorl    %eax, %eax
    addq    $40, %rsp
    .cfi_remember_state
    .cfi_def_cfa_offset 8
    ret
.L5:
    .cfi_restore_state
    call    __stack_chk_fail@PLT
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0"
    .section    .note.GNU-stack,"",@progbits

告诉我们 gcc 根本没有将字符串数据放入汇编代码中。相反,如果我将“字符串”声明为“易失性”,它就可以正常工作。

但是,“易失性”的想法只是将它用于可以通过(从执行函数的角度)意外事件来改变其值的变量,不是吗?“volatile”会使代码变慢,因此应尽可能避免。

正如我所想的那样,gcc 必须假设不能忽略“string”的内容,因为指针“string”被用作内联汇编中的输入参数(并且 gcc 不知道内联汇编代码将如何处理它) )。

如果这是 gcc 的“允许”行为,我在哪里可以阅读更多关于为 -O3 编写代码时必须注意的所有形式约束的信息?

第二个问题是“易失性”语句与内联汇编指令的确切作用。我只是习惯于用“volatile”标记所有内联汇编指令,因为在某些情况下它无法正常工作。

标签: cgccoptimizationinline-assembly

解决方案


推荐阅读