Сообщить разработчикам gcc?

Система Fedora 24, gcc version 6.3.1 20161221, параметры для компилятора -m64 -ffreestanding -O0 Компилирую, в том числе, следующий код

void set_int_handler(uint8 index, void *handler, uint8 type)
{
    asm("pushf \n cli");
    idt[index].selector = 8;
    idt[index].address_0_15 = (size_t)handler & 0xFFFF;
    idt[index].address_16_31 = (size_t)handler >> 16;
    idt[index].type = type;
    idt[index].reserved_IST = 0;
    idt[index].address_32_63 = (size_t)handler >> 32;
    idt[index].reserved2 = 0;
    asm("popf");
}

Компилятор видит что внутри функции нет других вызовов и пропускает инструкцию выделения памяти в стеке (sub rsp, <размер>). Перемещает параметры на место локальных переменных и когда выполняется PUSHF, затирает эти параметры. Как это обойти я знаю. Нужно ли сообщать разработчикам gcc об ошибке, или это не ошибка. Может я неправильно пишу на СИ (может какой то параметр нужно указать компилятору?)

Ассемблерный листинг

set_int_handler:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
; копируем указатель стека в RBP
    movq    %rsp, %rbp
; здесь при -m32 sub rsp, <size>
    .cfi_def_cfa_register 6
    movl    %edi, %ecx
    movq    %rsi, -16(%rbp)
    movl    %edx, %eax
    movb    %cl, -4(%rbp)
; gcc перемещает параметр в область локальных переменных
    movb    %al, -8(%rbp)
#APP
# 114 "interrupts.c" 1
; PUSHF затирает RBP - 4
    pushf

Код для баг-репорта

#include <stdio.h>

short func(short p1, short p2, short p3)
{
    asm("pushf \n popf");
    return p1 + p2 + p3 + 1;
}

void main(void)
{
    short a, b, c, d;

    b = 3;
    c = 4;
    d = 5;
    a = func(b, c, d);
    printf("%d  %d  %d  %d\n", a, b, c, d);
}

gcc -m64 -o main64 main.c

gcc -m32 -o main32 main.c


Ответы (1 шт):

Автор решения: Jack Katch

Поддержка отреагировала на баг-репорт. Написали что я попал в red zone. Теория "Аблязов. Программирование на ассемблере для x86_64. стр.240 5.1.3 Модель вызова". Идея в следующем, предлагается для ускорения не использовать команду PUSH, а использовать MOV когда параметров у функции много (их через регистры передают, а число их конечно) их сохраняют таким образом в стек, предварительно выделив там место. Не уверен (см. док.) но соглашение о вызовах (64) предусматривает область в 128 байт (red zone) для параметров процедуры. gcc чтобы быть "быстрым" пишет туда, не выделяя память (мне это не нравится) т.е. не передвигая указатель стека (gcc -m32 это делает). Есть флаг -mno-red-zone который заставляет gcc передвинуть указатель стека. Это не ошибка а так задумано. Не попадайтесь на это.

→ Ссылка