2015-11-05 7 views
1

Я пытаюсь перевести код C на код сборки i386, но так и не понял.Перевести псевдо-код на сборку

n=1; 
s=50; 
a=0; 
while(n > 0) { 
    a=s/n; 
    n=n-1; 
} 
print a; 

Код выше должен быть переведен на ассемблере через компилятор в результате:

.data 
variables: .space 104 
msg: .asciz "Message %d\n" 
.text 
.global main 
main: 
    push $1 
    pop variables+52 
    push $50 
    pop variables+72 
    push $0 
    pop variables+0 
L000: 
    push variables+52 
    push $0 
    pop %ebx 
    pop %eax 
    cmp %ebx,%eax 
    jl L001 
    push variables+72 
    push variables+52 
    pop %ebx 
    pop %eax 
    xor %edx,%edx 
    idivl %ebx 
    push %eax 
    pop variables+0 
    push variables+52 
    push $1 
    pop %ebx 
    pop %eax 
    sub %ebx,%eax 
    push %eax 
    pop variables+52 
    jmp L000 
L001: 
    push variables+0 
    push $msg 
    call printf 
    add $8,%esp 
leave 
ret 

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

Message 0 
Segmentation fault (core dumped) 
+2

Вы знаете, что существует команда [mov инструкция] (http://x86.renejeschke.de/html/file_module_x86_id_176.html), которая позволяет перемещать значения в и из памяти в регистры. Вы используете менее эффективный метод нажатия на вещи в стеке и выталкивания их в место назначения. –

ответ

4

Ошибка - «деление на ноль». jl L001 оставляет петлю, если (n < 0), но она должна уйти, если (n < = 0). Поэтому измените его на jle L001 (jle = прыжок, если он меньше или равен).

Кроме того, leave является неправильным. Нет пролога, который нужно отменить. Убери это.

+0

Спасибо. Я работаю над этим компилятором чуть больше трех дней, и моя голова начинает немного путаться. – seb

+1

@seb: Я бы рекомендовал компиляцию с опцией _GCC_ '-g3' для добавления отладочной информации. Затем используйте GNU Debugger (gdb) для одиночного шага через ваш код. Намного легче понять, как ваш код идет не так и что приводит к ошибке. –

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