News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Storing Fibonacci Sequence in Array (64 bit)

Started by Brogue, November 24, 2011, 07:20:40 PM

Previous topic - Next topic

Brogue

I wasn't sure whether to put this in here or the 64 bit assembler subforum, so feel free to move it. My problem is I can't seem to figure out how to store the fibonacci sequence into an array, this is what I have so far:

MAXSTR equ 256d ; maximum length of input string
LF equ 10d ; line feed character
CR equ 13d ; carrage return character
NL equ LF,CR ; combined line feed and return
DOUBLESPC equ LF,LF,CR ; used to produce double spacing
MAXARR equ 94d                                        ;Max number of array elements


INCLUDE io64.inc ; required for I/O routines
INCLUDE fpu_io64.inc ; required for FPU I/O routines

;.STACK is not used in 64 bit code
; The ML64 assembler provides a 4096 byte stack

EXTRN wsprintfA: PROC ;Windows API for printing ASCII to screen

.DATA
Intro     BYTE  NL, 'Welcome!' ,NL,NL, 'This program will calculate the first 94 Fibonacci numbers',NL
  BYTE 'and store them in an array. You will then be able to print or display the "Mean"'
  BYTE 'or "Standard Deviation" of all or any part of the array.',NL
  BYTE 'The program will also calculate the square root of a real number.',NL,NL,0

Menu1 BYTE NL, '1) Display ALL or any PART of the Fibonacci Array',NL
  BYTE '2) Display the "Mean" of ALL or any PART of the Array',NL
  BYTE '3) Display the "Standard Deviation" of ALL or any PART of the Array',NL
  BYTE '4) Calculate the Square Root of a Real number',NL
  BYTE '5) Quit',NL,0

fibprev QWORD ?
fibnext QWORD ?
fibval QWORD ? ;holds value of fibonacci array
fibcount QWORD ? ;counts number of variables in array
fibtotal QWORD ?
FibArray QWORD 94d dup(?) ;Holds fibonacci array
NextLine BYTE NL,0
lpFmt   BYTE '%25I64u',0
OutString BYTE MAXSTR dup(0)
ArrayPtr QWORD ? ;Pointer for array

.CODE
main PROC
sub rsp, 28h ; reserve stack space for five (5) qwords
;   which is the minimum for storing
;   rcx, rdx, r8, r9 and return address.
;   required even with no parameters passed
        lea rsi,Intro ; point to the Intro string
        call PrintStr ;   and print it
        lea rsi, Menu1
        call PrintStr
        lea rsi, FibArray
        call Fibonacci
        ;call PrintStr

        add rsp, 28h ; restore stack space
xor ecx, ecx        ; exit code = 0
        call ExitProcess ; exit to operating system
main ENDP

;--------------------- Procedure to calculate Fibonacci Array ---------------------------------
; Requires : 
; Process  : Calculates fibonacci array to 94th element 
;          :  All volitile registers are preserved.
; Return   : Fibonacci Array
;---------------------------------------------------------------------------------
Fibonacci PROC USES rax rcx rdx r8 r9 r10 r11 ;preserve volitile registers unless
;  you want to return values in them.
;  you may add any other registers you
;  want to preserve to the USES line.
;  rbx, rsi, rdi, rbp, and rsp are
;  the programmers responsiblity and
;  should be protected on the USES line.

sub  rsp, 28h ; reserve stack space for local calls.
; you will need to increase the number by 8
; for each parameter you use beyond the first 4,
; which are always passed in rcx, rdx, r8, and r9.
mov rcx, MAXARR ;counts 94 elements
mov fibval, 1
mov fibprev, -1
mov rax, 1

fibloop:
;cmp rcx, 0

mov fibcount, rcx
mov rbx, fibval
add rbx, fibprev
mov fibtotal, rbx
mov rbx, fibval
mov fibprev, rbx
mov rax, fibtotal
mov fibval, rax
stosq
loop fibloop


arrayout:
lodsq
mov r8, rax
push rsi
lea rsi,FibArray
call PrintStr
pop rsi
loop arrayout



; Put your code here

add  rsp, 28h ; restore stack space used for local calls             
ret ; return to caller
Fibonacci ENDP

END ; End of the code segment


Any help is appreciated.

qWord

; IN: rcx = number of QWORDs (=94)
;     rdx = ptr Array
Fibonacci proc

mov r10,2
xor r8,r8
mov r9,1
mov [rdx],r8
mov [rdx+1*8],r9

@1: mov rax,r9
lea r9,[r9+r8]
mov r8,rax
mov [rdx+r10*8],r9
lea r10,[r10+1]
cmp r10,rcx
jb @1

ret

Fibonacci endp

BTW:  you should use jwasm instead of ml64
FPU in a trice: SmplMath
It's that simple!

Brogue

Fibonacci PROC USES rax rcx rdx r8 r9 r10 r11 ;preserve volitile registers unless
;  you want to return values in them.
;  you may add any other registers you
;  want to preserve to the USES line.
;  rbx, rsi, rdi, rbp, and rsp are
;  the programmers responsiblity and
;  should be protected on the USES line.

sub  rsp, 28h ; reserve stack space for local calls.
; you will need to increase the number by 8
; for each parameter you use beyond the first 4,
; which are always passed in rcx, rdx, r8, and r9.

mov rcx, MAXARR
mov rdx, ArrayPtr
mov r10,2
xor r8,r8
mov r9,1
mov [rdx],r8
mov [rdx+1*8],r9

fibloop: mov rax,r9
lea r9,[r9+r8]
mov r8,rax
mov [rdx+r10*8],r9
lea r10,[r10+1]
cmp r10,rcx
jb fibloop
; Put your code here
add  rsp, 28h ; restore stack space used for local calls             
ret ; return to caller
Fibonacci ENDP


I'm getting an unhandled exception error at "mov [rdx],r8" and I'm not sure why. Also, I unfortunately cannot use jwasm, I must use ml64.

qWord

probably ArrayPtr is not initialized.
You should call the shown function similarly to this:
lea rdx,FibArray
mov rcx,LENGTHOF FibArray
call Fibonacci

Also:
- the sub/add rsp,28h is not needed, because there are no function calls in Fibonacci
- 28h = 5*8 -> for 4 parameters only 4*8 bytes are needed. The additional 8 bytes are added for alignment purpose (align 16), which is a WinAPI requirement.
- in context to the WinAPI, there is no need to preserve rdx,rcx,r8,r9,r10 and r11 (x64 Register Usage)
( - stay away from global variables )
FPU in a trice: SmplMath
It's that simple!

Brogue

I thought I had initialized the array pointer variable in my .Data segment, but you tell me to avoid global variables, then what should I do to have ArrayPtr initialized properly?


qWord

you can still use globals:
main proc

add rsp,-5*8

.data
array QWORD 94 dup (?)
parray QWORD OFFSET array
.code

mov rdx,parray
mov rcx,LENGTHOF array
invoke Fibonacci

;...

add rsp,5*8
ret
main endp
FPU in a trice: SmplMath
It's that simple!

Brogue

Okay, I've gotten rid of all the errors I was having,  but now I'm trying to actually display what is in the Fibonacci Array, Thinking of using the wsprintfA API call, but I'm not sure how to go about doing it. The MSDN Library says

Process  : Set up the parameters and call Windows API wsprintfA to create a
         : properly formatted Ascii string to be printed.
         int __cdecl wsprintf(;            __out  LPTSTR lpOut, (rcx pointing to output string in data segment)
            __in   LPCTSTR lpFmt, (rdx pointing to format string in data segment)
            __in   QWORD (r8 containing the qword to print)
         );
         
But I'm not exactly sure what the input and output requirements are in relation to the Fibonacci function. I don't believe that r8 has the qword data in it.

qWord

For writing a __int64-value to the console (with line break):
; use msvcrt functions
; includelib msvcrt.lib
printf proto pszFrmt:ptr BYTE,args:VARARG
;...
.data
szFrmt db "%I64d",13,10,0
.code
;...
mov rdx,12345
mov rcx,OFFSET szFrmt
call printf
FPU in a trice: SmplMath
It's that simple!