c - 如果 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”标记所有内联汇编指令,因为在某些情况下它无法正常工作。
解决方案
推荐阅读
- mysql - 如何优化日期时间条件的查询?
- xunit - 如何将包含测试文件的目录传递给 xUnit 测试?
- java - 如何在外部mysql数据库之间建立连接,然后调用特定的数据查询
- javascript - 具有分配给它的惰性值的节点咖喱函数
- mule - 在地图迭代中获取父索引
- c# - 无法从 C# 正确执行 devenv
- java - 运行整个课程时如何跳过一种方法到另一种方法?
- linux - Curl 没有在 Centos 中安装 ssl 支持(在用户定义的 --perfix 中)
- node.js - Gatsby 节点 api 没有给出值“fileAbsolutePath”
- java - RelativeLayout 无法转换为 TextView