Почему простая программа на языке «hello world» на C не работает, если gcc -O3 без «volatile»? - PullRequest
0 голосов
/ 30 ноября 2018

У меня есть следующая программа на C

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

, которую я хочу запустить под Linux с 64-битной x86.Я вызываю системный вызов для «записи» с 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 просто не поместил строковые данные в код сборки.Вместо этого, если я объявляю «string» как «volatile», он работает нормально.

Однако идея «volatile» состоит в том, чтобы просто использовать его для переменных, которые могут изменять свои значения (с точки зрениявыполнение функции) неожиданные события, не так ли?«volatile» может сделать код намного медленнее, поэтому его следует избегать, если это возможно.

Как я полагаю, gcc должен предполагать, что содержимое «string» не должно игнорироваться, поскольку используется указатель «string»в качестве входного параметра во встроенной сборке (и gcc не знает, что с ней будет делать код встроенной сборки).

Если это «разрешенное» поведение gcc, где я могу прочитать больше обо всех формальныхограничения, о которых я должен знать, когда пишу код для -O3?

Второй вопрос заключается в том, что именно делает выражение «volatile» вместе с директивой встроенной сборки.Я просто привык помечать все директивы встроенной сборки как «volatile», потому что в некоторых ситуациях это не сработало.

...