Код Y86 не обрабатывает команду ret, как ожидалось - PullRequest
1 голос
/ 13 мая 2011

Ниже приведена домашняя задача для класса на ассемблере.Мы должны создать код Y86, читая код X86, сгенерированный из C в GDB.Назначение функции - суммировать элементы связанного списка.

В настоящее время функция работает, она работает!Правильное значение содержится в регистре% eax после завершения программы.К сожалению, это правильно только из-за взлома.Я добавил инструкцию halt прямо в конце функции, прямо перед инструкцией ret.Если я раскомментирую это, то произойдет то, что при выполнении инструкции ret ПК устанавливается на 0x0.Другими словами, кажется, что все начинается сначала, когда то, что он должен сделать, это вернуться к точке, где он был вызван.Он входит в бесконечный цикл.

Код следует.Это автономно, если у вас установлен симулятор Y86.

.pos    0
init:    irmovl Stack, %esp  
irmovl    Stack, %ebp  
jmp     Main  

Main:  
    irmovl  ele1, %eax  
    pushl   %eax  
    call    sum_list  
    halt  

sum_list:  
    pushl   %ebp  
    rrmovl  %esp, %ebp  
    irmovl  $16, %edx  
    subl    %edx, %esp  
    irmovl  $0, %edx  
    rmmovl  %edx, -4(%ebp)  
    jmp     L2  

L3:
    mrmovl  8(%ebp), %eax
    mrmovl  (%eax), %eax
    mrmovl  -4(%ebp), %edx
    addl    %eax, %edx
    rmmovl  %edx, -4(%ebp)
    mrmovl  8(%ebp), %eax
    mrmovl  4(%eax), %eax
    rmmovl  %eax, 8(%ebp)

L2:
    irmovl  $0, %ecx
    mrmovl  8(%ebp), %edx
    subl    %ecx, %edx
    jne     L3
    mrmovl  -4(%ebp), %eax
    rrmovl  %esp, %ebp
    popl    %ebp
    halt #THIS DOESN'T BELONG. COMMENT OUT TO SEE BAD BEHAVIOR.
    ret

#linked list
.align  4
    ele1:
            .long   0x00a
            .long   ele2
    ele2:
            .long   0x0b0
            .long   ele3
    ele3:
            .long   0xc00
            .long   0


    .pos    0x300
    Stack:

Спасибо за вашу помощь!

Ответы [ 3 ]

4 голосов
/ 13 мая 2011

Это может быть, а может и не быть причиной ошибки, но я думаю, что вы неправильно разбиваете стек стека sum_list.Вы устанавливаете его следующим образом:

pushl   %ebp  
rrmovl  %esp, %ebp

, но затем разбиваете его следующим образом:

rrmovl  %esp, %ebp
popl    %ebp

Обратите внимание, что вы копируете из %esp в %ebp в обоих случаях,что не правильно, так как демонтаж должен отменить то, что делает установка.Вместо этого попробуйте

rrmovl  %ebp, %esp
popl    %ebp

или просто

leave

, который делает то же самое.

0 голосов
/ 08 ноября 2012

Есть две (с половиной) проблемы, связанные с манипуляциями со стеком:

Фрейм настроен правильно, но часть деконструкции не выполняется (программа выполняет rrmovl% esp,% ebp вместо rrmovl% ebp,% esp)

Попытка получить доступ к параметру, сохраненному в предыдущем кадре (то есть кадре вызывающего абонента), не удалась.Стек выполняется сверху и снизу, а последними элементами, хранящимися в стеке, являются адрес возврата и указатель старого кадра, поэтому после изменения регистра ebp вызываемый объект может напрямую обращаться к аргументам вызывающей функции посредством прогрессивного смещения, начиная с8 (% ebp).

Половина ошибки заключается в том, что основная функция не извлекает сохраненный параметр стека до его завершения.

Соглашение между вызывающими и вызываемыми абонентами обсуждается в моем блоге Y86в http://y86tutoring.wordpress.com/2012/10/31/functioning-stacks/

0 голосов
/ 13 мая 2011
mrmovl  -4(%ebp), %edx

здесь проблема. на ebp - 4 есть обратный адрес, поэтому вы перезаписываете его. Используйте другое место, и все будет хорошо:)

...