GCC не работает при получении адреса аргумента в ARM7TDMI? - PullRequest
4 голосов
/ 26 августа 2008

Мой фрагмент кода C принимает адрес аргумента и сохраняет его в энергозависимой памяти (предварительно обработанный код):

void foo(unsigned int x) {
    *(volatile unsigned int*)(0x4000000 + 0xd4) = (unsigned int)(&x);
}

int main() {
    foo(1);
    while(1);
}

Я использовал SVN-версию GCC для компиляции этого кода. В конце функции foo я ожидал бы, что в стеке будет храниться значение 1, а при 0x40000d4 адрес будет указывать на это значение. Когда я компилирую без оптимизации, используя флаг -O0, я получаю ожидаемый вывод сборки ARM7TMDI (закомментирован для вашего удобства):

        .align  2
        .global foo
        .type   foo, %function
foo:
        @ Function supports interworking.
        @ args = 0, pretend = 0, frame = 8
        @ frame_needed = 0, uses_anonymous_args = 0
        @ link register save eliminated.
        sub     sp, sp, #8
        str     r0, [sp, #4]     @ 3. Store the argument on the stack
        mov     r3, #67108864
        add     r3, r3, #212
        add     r2, sp, #4       @ 4. Address of the stack variable
        str     r2, [r3, #0]     @ 5. Store the address at 0x40000d4
        add     sp, sp, #8
        bx      lr
        .size   foo, .-foo
        .align  2
        .global main
        .type   main, %function
main:
        @ Function supports interworking.
        @ args = 0, pretend = 0, frame = 0
        @ frame_needed = 0, uses_anonymous_args = 0
        stmfd   sp!, {r4, lr}
        mov     r0, #1           @ 1. Pass the argument in register 0
        bl      foo              @ 2. Call function foo
.L4:
        b       .L4
        .size   main, .-main
        .ident  "GCC: (GNU) 4.4.0 20080820 (experimental)"

Он явно сохраняет аргумент сначала в стеке, а оттуда сохраняет его в 0x40000d4. Когда я компилирую с оптимизацией, используя -O1, я получаю нечто неожиданное:

        .align  2
        .global foo
        .type   foo, %function
foo:
        @ Function supports interworking.
        @ args = 0, pretend = 0, frame = 8
        @ frame_needed = 0, uses_anonymous_args = 0
        @ link register save eliminated.
        sub     sp, sp, #8
        mov     r2, #67108864
        add     r3, sp, #4        @ 3. Address of *something* on the stack
        str     r3, [r2, #212]    @ 4. Store the address at 0x40000d4
        add     sp, sp, #8
        bx      lr
        .size   foo, .-foo
        .align  2
        .global main
        .type   main, %function
main:
        @ Function supports interworking.
        @ args = 0, pretend = 0, frame = 0
        @ frame_needed = 0, uses_anonymous_args = 0
        stmfd   sp!, {r4, lr}
        mov     r0, #1           @ 1. Pass the argument in register 0
        bl      foo              @ 2. Call function foo
.L4:
        b       .L4
        .size   main, .-main
        .ident  "GCC: (GNU) 4.4.0 20080820 (experimental)"

На этот раз аргумент никогда не сохраняется в стеке, даже если что-то из стека все еще хранится в 0x40000d4.

Это просто ожидаемое / неопределенное поведение? Я сделал что-то не так или действительно нашел ошибку компилятора & trade;?

Ответы [ 11 ]

0 голосов
/ 26 августа 2008

Это просто ожидалось / не определено поведение? Я сделал что-то не так или я на самом деле нашел компилятор Ошибка ™? * * 1002

Нет ошибки, только определенное поведение, при котором опции оптимизации могут создавать странный код, который может не работать:)

EDIT:

Если вы считаете, что обнаружили ошибку в GCC, списки рассылки будут рады, что вы зашли, но, как правило, они находят какую-то дыру в ваших знаниях, чтобы обвинять и безжалостно насмехаться: (

В этом случае я думаю, что, вероятно, опции -O, пытающиеся создать ярлыки, которые ломают ваш код, требуют обхода.

...