Ich schrieb dieses einfache Programm, um ein i-tes Element einer rekursiven Sequenz zu berechnen. Die Reihenfolge sieht grundsätzlich wie folgt aus:Register für IMUL-Befehl
a(n)=a(n-1)*a(n-2)
mit den ersten beiden Elementen -1 und -3. Ich verwende imul
zum Multiplizieren und aufgrund meiner Ergebnisse im Netz sollte ich in der Lage sein, alle gewünschten Register zu verwenden, aber das Programm gibt 0 für das dritte Element zurück. Bei Umschaltung auf add
funktioniert es wie vorgesehen. Hier ist das Fragment, wo ich die Funktion rekursiv aufrufen und sich vermehren (wie gesehen, ich Stack verwenden, um meine Variablen zu speichern)
push %rcx
push %rax
call calculate
pop %rax
pop %rcx
imul %rcx, %rbx
Grundsätzlich Frage „warum es nicht funktioniert“: P
PS. Falls vollständiger Code benötigt:
.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
Bitte posten Sie den vollständigen Code inline in Ihrer Frage. – fuz
Da gehen Sie hin. Ich dachte, es wird die Frage kürzer machen, wenn ich einen Link zu Pastebin einfügen – Wylfryd