x86-64 рекурсивная функция умножения - PullRequest
1 голос
/ 02 марта 2020

Я пытаюсь создать функцию в сборке x86-64, которая умножает два числа x и y и возвращает результат без использования al oop или оператора mul. Это код, который я придумал, но я не знаю, почему он всегда возвращает y. Любая помощь приветствуется. x в edi, y в esi.

mul:
    xorl %eax, %eax
    testl %edi, %edi  #if x == 0 return 0 //base case 1
    je done1
    testl %esi, %esi  #if y == 0 return 0 //base case 1
    je done1

    cmpl $1, %edi   #if x == 1, return y //base case 2
    je done2

    addl %esi, %eax   #add eax by y (esi) x (edi) times
    decl %edi       #decrease x by 1 each run of the function. B stays the same
    call mul

done1:
    ret

done2:              #if x == 1, return y
    movl %esi, %eax
    ret

1 Ответ

3 голосов
/ 02 марта 2020

Всегда возвращает «y», потому что вы уменьшаете %edi на

decl %edi

, пока не достигнете значения «1». Затем выполняется следующая последовательность команд:

call mul          # CALL -->
...
xorl %eax, %eax   # RESET accumulator value to 0
testl %edi, %edi  
je done1          # NOT TAKEN
testl %esi, %esi  
je done1          # NOT TAKEN
cmpl $1, %edi     # if x == 1, return y //base case 2
je done2          # HERE - THIS JUMP IS TAKEN
...
movl %esi, %eax   # MOVE y to return register %eax
ret               # It always returns y in %eax

Чтобы исправить эту ситуацию, сначала переместите строку xorl %eax, %eax перед меткой mul. Затем удалите строку movl %esi, %eax, чтобы сохранить значение %eax в качестве возвращаемого значения.

Так что это может быть решением:

    xorl %eax, %eax   # Set result value to "0"
    # check for 0 for "y" input 
    testl %esi, %esi  # if y == 0 return 0 //base case 1
    je done1          # immediately return on zero
mul:    
    test %edi, %edi   # if x == 0, exit recursive calls
    je done1
    addl %esi, %eax   # add y (esi) to eax 
    decl %edi         # decrease x by 1 each run of the function. B stays the same
    call mul
    # PASS-THROUGH on stack unwinding
done1:
    ret

Отказ от ответственности: я не проверял, но Вы должны получить идею.

...