2017-05-20 1 views
1

J'écrivais ce programme simple pour calculer un ième élément d'une séquence récursive. La séquence ressemble essentiellement àRegistres pour l'instruction IMUL

a(n)=a(n-1)*a(n-2) 

avec les deux premiers éléments étant -1 et -3. J'utilise imul pour multiplier et en raison de mes conclusions dans le réseau, je devrais être en mesure d'utiliser tous les registres que je veux, mais le programme retourne 0 pour le troisième élément. Lorsqu'elle est commutée sur add, cela fonctionne comme prévu. est ici le fragment où j'appelle récursivement la fonction et se multiplient (comme on le voit, j'utiliser la pile pour stocker mes variables) Fondamentalement question

push %rcx 
push %rax 
call calculate 
pop %rax 
pop %rcx 
imul %rcx, %rbx 

est « pourquoi il ne fonctionne pas »: P

PS. Dans le cas où le code complet est nécessaire:

.data 
STDOUT = 1 
SYSWRITE = 1 
HOW_MANY = 3    # which number to calculate 
SYSEXIT = 60 
EXIT_SUCCESS = 0 
FIRST = -1     # first element of the sequence 
SECOND = -3     # second element of the sequence 
NUMBER_BEGIN = 0x30 
OUTPUT_BASE = 10 
NEW_LINE = '\n' 
PLUS = '+' 
MINUS = '-' 

.bss 
.comm textin, 512 
.comm textout, 512 
.comm text2, 512 
.comm znak, 1 

.text 
.globl _start 

_start: 

# 
# Calling function to calculate ith element 
# 
mov $HOW_MANY, %r8 
sub $1, %r8 
push %r8     # push r8 (function argument) to stack 
call calculate    # call function to calculate 
add $8, %rsp    # removing parameter from stack 

# now we should've have result in rbx 
# 
mov $0, %r15 # Flaga znaku (domyślnie 0 = +) 
cmp $0, %rbx 
jge to_ascii # Pomiń jeśli liczba jest dodatnia 
not %rbx # Odwrócenie bitów liczby i dodanie 1, 
inc %rbx # aby uzyskać jej wartość bezwzględną. 
mov $1, %r15 # Ustawienie flagi znaku na 1 = -. 

to_ascii: 
mov %rbx, %rax # result goes to rax 
mov $OUTPUT_BASE, %rbx 
mov $0, %rcx 
jmp loop 

loop: 
mov $0, %rdx 
div %rbx # divide rax by rbx, rest in rdx 
add $NUMBER_BEGIN, %rdx # rest in rdx is a next position number 
mov %dl, text2(, %rcx, 1) 

inc %rcx 
cmp $0, %rax 
jne loop 
jmp inverse 

inverse: 
mov $0, %rdi 
mov %rcx, %rsi 
dec %rsi 
jmp inversev2 

inversev2: 
mov text2(, %rsi, 1), %rax 
mov %rax, textout(, %rdi, 1) 
inc %rdi 
dec %rsi 
cmp %rcx, %rdi 
jle inversev2 

push %rcx # legth of the answer goes to stack 

mov $0, %r10 # want sign at the first position 
movb $PLUS, znak(, %r10, 1) 

cmp $0, %r15 # r15 register contains info about the sign 
je next # 0 = +, so nothing has to be done 

movb $MINUS, znak(, %r10, 1) # otherwise set it to minus 

next: # show sign 
mov $SYSWRITE, %rax 
mov $STDOUT, %rdi 
mov $znak, %rsi 
mov $1, %rdx 
syscall 

pop %rcx 

movb $NEW_LINE, textout(, %rcx, 1) 
inc %rcx 

mov $SYSWRITE, %rax 
mov $STDOUT, %rdi 
mov $textout, %rsi 
mov %rcx, %rdx 
syscall 

mov $SYSEXIT, %rax 
mov $EXIT_SUCCESS, %rdi 
syscall 

# recursive function calculating ith element of a given sequence 
# sequence = 
# n_1 = -1 
# n_2 = -3 
# n_i = n_(i-1)*n_(i-2) 
calculate: 
push %rbp     # push rbp to stack to save it's value 
mov %rsp, %rbp    # now stack pointer is stored in rbp 

sub $8, %rsp 
mov 16(%rbp), %rax 

cmp $1, %rax 
jl first 
je second 

mov $0, %rcx 

# wywołanie dla n_(i-1) 
dec %rax 

push %rcx 
push %rax 
call calculate 
pop %rax 
pop %rcx # przepisać na rejestry imula 
imul %rcx, %rbx 

# wywołanie dla n_(i-2) 
dec %rax 
push %rcx 
push %rax 
call calculate 
pop %rax 
pop %rcx 
imul %rcx, %rbx 

return: 
mov %rcx, %rbx 
mov %rbp, %rsp 
pop %rbp 
ret 

first: 
mov $FIRST, %rbx 
mov %rbp, %rsp 
pop %rbp 
ret 

second: 
mov $SECOND, %rbx 
mov %rbp, %rsp 
pop %rbp 
ret 
+0

S'il vous plaît poster le code complet en ligne dans votre question. – fuz

+0

Voilà. Je pensais que cela rendra la question plus courte si j'ajoute un lien à pastebin insted – Wylfryd

Répondre

3

Vous semez% rcx à zéro, puis en multipliant dans ce, alors vous aurez toujours un produit de zéro.

Peut-être que vous voulez changer

mov $0, %rcx 

à

mov $1, %rcx 

Je pense que vous avez aussi besoin d'inverser la

imul %rcx, %rbx 

à

imul %rbx, %rcx 

(Je ne suis pas familier avec cette saveur de l'assembleur)

+0

Je me sens comme un idiot maintenant ... -.- Merci beaucoup! – Wylfryd

+0

Et oui, j'ai déjà changé cela, parce que je veux que mon résultat soit dans '% rcx' et non dans '% rbx' – Wylfryd