2015-07-18 2 views
2

Недавно я играл с сборкой, и я наткнулся на странную ошибку в моей программе. Я обнаружил, что если я модифицирую %rsp, выполнив 64-битную математику, тогда все будет хорошо, но если я изменю %esp на ту же сумму, за исключением 32-битной математики, я получаю ошибку сегментации. Я попробовал распечатать как %esp, так и %rsp, и они одинаковы при каждом запуске.x86_64 сборка% rsp vs% esp

ВОПРОС: Почему имеет значение, выполняю ли 64-битную математику или 32-битную математику, когда весь регистр использует только 32 бита?

.cstring 
    _format: .asciz "%d\n" 

.text 
.globl _main 
_main: 
    # program setup 
    pushq %rbp 
    movq %rsp, %rbp 

    # program - 16 byte aligned at this point 
    # print stack pointer memory 
    movq %rsp, %rax 
    call bob   # prints the same value as the next call to bob 
    xorq %rax, %rax 
    movl %esp, %eax 
    call bob   # prints the same value as previous call to bob 

    # this code breaks 
    subl $16, %esp  # bug here if I use this (32 bit math) 
    subq $16, %rsp  # works fine if I use this (64 bit math) 
    call bob 
    addq $16, %rsp 

    # program cleanup 
    movq %rbp, %rsp 
    popq %rbp 
    ret 

# assumes 16 byte aligned when called. Prints %rax 
bob: 
    subq $8, %rsp 
    movq %rax, %rsi 
    lea  _format(%rip), %rdi 
    call _printf 
    addq $8, %rsp 
    ret 
+4

subl $ 16,% esp устанавливает верхние 32 бита RSP равным нулю. Kaboom. [Разъясняется здесь] (http://stackoverflow.com/a/25456097/17034). –

+0

Связанные: http://stackoverflow.com/questions/15656887/a-modification-to-esp-cause-sigsegv – nrz

ответ

2

В x86_64 адреса имеют 64 бита, поэтому как вы можете ожидать выполнения 32-битной математики и все еще нормально работать? Более того, большинство 32-разрядных операций на x86_64 обнуляют верхние 32 бита, делают адрес недействительным

+1

Не только большинство. Каждая инструкция, использующая 32-битный регистр '% esomething', как результат, обнуляет верхнюю 32. Таким образом, они не зависят от предыдущего значения регистра, для выполнения вне порядка. –

1

С помощью разговора с KerrekSB причиной несоответствия является ошибка печати. Когда я сказал, что напечатал как RSP, так и ESP, я сделал это с %d в вызове _printf, который печатает 4 байта. При применении к RSP он печатал только 4 байта (эквивалентно ESP), что заставило меня думать, что RSP имеет только содержательные данные в младших 4 байтах. Когда я изменил его для печати %lu, я обнаружил, что RSP и ESP действительно не эквивалентны, а RSP был, используя верхние 4 байта. Вот почему 32-битная математика вызвала ошибку сегментации.

+2

См. Http://stackoverflow.com/tags/x86/info для ссылок на руководства и информацию об использовании gdb в коде asm. Это поймало бы вашу ошибку. –

Смежные вопросы