So...is this the soapbox? :biggrin: Just kidding.
I have written this simple program that will calculate and write an arbitrary amount of the fibonacci numbers serie into a file. Please note that the source code and an .exe file are in the .zip file. What i try to say with this is that just 1 possible error (from a large spectrum of errors i guess, but maybe they are not so many actually) is notified in this version of the program: if the buffer for the actual directory of the user is too small. There are no checking errors for "write to the file" problems, like dealing with permissions and possibly others. So please feel free to modify this code to whatever you need, including all those error checkings if you want. :idea:
I have done this program (the loaded to the forum version) to write just 100 fibonacci numbers to a .txt file. But i have tried with 1000 numbers too and it seemed that worked good to me. By the way there are no error checking, for numbers supplied in the source code that can be really big (i mean if you supply to the program to calculate a really big number of fibonacci numbers). I suposse that this situation will need basically a bigger buffer to store each number. The one is used in this version is of approximately 256 bytes for each fibonacci number transformed to ascii, but the binary fibonacci number limit size used is that of a 32 bit register (you know that size)... :idea:
Finally, i want to make clear (by the way sorry for my english again :redface:) that all this introduction of what is supplied here, from me to all of you, doesn't mean i don't want to receive critics or similars. Please note that this program was done like that mainly for clarity. So all your comments are welcome! :icon14:
Quote
I have done this program (the loaded to the forum version) to write just 100 fibonacci numbers to a .txt file
It appears that you are not concerned with the 32-bit overflow :biggrin:
which will happen on and after the 48th Fibonacci number.
:redface: Thanks for telling me that! Well i guess i understimated how this numbers can grow. I was thinking of doing a 64 bit version after this 32 bit version. But maybe i will repair this version first to support properly at least 100 fibonacci numbers. Thanks again, i was actually wishing someone could tell me if the numbers were all correct or not (something that i supossed was difficult to do manually). :icon14:
If this is simply an exercise in curiosity, and you are not concerned with an ultrafast algo, you may want to try using binary coded decimals http://www.ray.masmcode.com/BCDtut.html.
You could then go as far as you want, the memory require being only approx. three times the number of digits required for the largest one, a third of that being for the ascii converted number. Each new converted number could then be added to the end of an open file without worrying about memory required for the entire file.
Felipe if you make this work correctly,it would be Worth much for students who usually get fibonacci as task,C#,c++,java etc
the question I asked myself was if it somehow was possible to make a SIMD solution?
and the question is does there exist something similar algo for fibonacci,that exist an alternative x! algo for approximation of high numbers
I just did it using ascii characters, 60 char wide, easily expandable. Thanks for the fun diversion :)
; by JimG
.nolist
.586
.model flat, stdcall
option casemap:none ; case sensitive
include windows.inc
uselib Macro libname:req
include libname.inc
includelib libname.lib
Endm
uselib kernel32
uselib user32
inv equ invoke
maxsize=60 ; max width of answers
.data?
hout dd ?
nout dd ?
ncnt dd ?
cary db ?
.data
val1 db maxsize-1 dup (" "),"1",13,10,0
val2 db maxsize-1 dup (" "),"1",13,10,0
val3 db maxsize-1 dup (" "),"0",13,10,0
.code
Program:
inv GetStdHandle,STD_OUTPUT_HANDLE
mov hout,eax
inv WriteFile,hout,addr val1,maxsize+2,addr nout,0
inv WriteFile,hout,addr val2,maxsize+2,addr nout,0
pusha
lea esi,val1 ; previous val
lea edi,val2 ; previous val
lea ebx,val3 ; new val
mov ncnt,2
.repeat
mov ecx,maxsize-1 ; 0 to max
mov cary,0
.repeat
mov eax,0
mov al,byte ptr [esi+ecx]
mov dl,byte ptr [edi+ecx]
.if al==" "
mov al,'0'
.endif
.if dl==" "
mov dl,'0'
.endif
sub al,'0' ; convert to binary
sub dl,'0'
add al,dl
add al,cary
mov cary,0
.if al>9
mov cary,1
sub al,10
.endif
add al,'0' ; convert to ascii
mov [ebx+ecx],al
dec ecx
jz maxdone
.if byte ptr [edi+ecx]==" " ; are we done?
.if cary
mov byte ptr [ebx+ecx],'1'
.endif
.break
.endif
.until 0
inv WriteFile,hout,ebx,maxsize+2,addr nout,0
mov eax,esi ; where next answer will go
mov esi,edi
mov edi,ebx
mov ebx,eax
inc ncnt
.until 0
maxdone: inv Sleep,100000
popa
inv ExitProcess,0
End Program
very quick and dirty, can be cleaned up a lot :)
Quote from: daydreamer on July 07, 2018, 03:05:31 AM
the question is does there exist something similar algo for fibonacci,that exist an alternative x! algo for approximation of high numbers
there's a closed form formula for Fibonacci numbers, F(n) = (((1+sqrt(5))*(1/2))^n-((1-sqrt(5))*(1/2))^n)/sqrt(5) https://en.wikipedia.org/wiki/Fibonacci_number#Closed-form_expression
Thanks raymond i will check that tutorial for sure. Hey jimg, that looks great, nice work.
:icon14:
Hello, here it's a 64 bit version of the same program i wrote (which by the way also had a wrong date, indicating the creation of the program in the future :P). This version can easily produce the first 100 fibonacci numbers in the file as can be seen here:
2-3-5-8-13-21-34-55-89-144-233-377-610-987-1597-2584-4181-6765-10946-17711-28657-46368-75025-121393-196418-317811-514229-832040-1346269-2178309-3524578-5702887-9227465-14930352-24157817-39088169-63245986-102334155-165580141-267914296-433494437-701408733-1134903170-1836311903-2971215073-4807526976-7778742049-12586269025-20365011074-32951280099-53316291173-86267571272-139583862445-225851433717-365435296162-591286729879-956722026041-1548008755920-2504730781961-4052739537881-6557470319842-10610209857723-17167680177565-27777890035288-44945570212853-72723460248141-117669030460994-190392490709135-308061521170129-498454011879264-806515533049393-1304969544928657-2111485077978050-3416454622906707-5527939700884757-8944394323791464-14472334024676221-23416728348467685-37889062373143906-61305790721611591-99194853094755497-160500643816367088-259695496911122585-420196140727489673-679891637638612258-1100087778366101931-1779979416004714189-2880067194370816120-4660046610375530309-7540113804746346429-12200160415121876738-1293530146158671551-13493690561280548289-14787220707439219840-9834167195010216513-6174643828739884737-16008811023750101250-3736710778780434371-1298777728820984005-5035488507601418376
The source code and the .exe are attached. :icon14:
If we start the series with F1= 1 and F2=1, then F3=2, etc.
F93=12200160415121876738 which is the last one in your list which is correct.
You can easily see that your following listed number(s) cannot be the sum of the two previous ones.
Here's a short program using BCDs to compute Fibonacci numbers which you can adapt as needed. As is, it terminates when a given number of digits is reached. Instead, it could be terminated when a given Fn is reached.
BTW, F476 is the first one to contain 100 digits.
; Fibonacci numbers
; For computing the first Fibonacii having a specified number of decimal digits
; #########################################################################
.686 ; minimum processor needed for 32 bit
.model flat, stdcall ; FLAT memory model & STDCALL calling
option casemap :none ; set code to case sensitive
; #########################################################################
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
.data
FibA db 1,99 DUP(0) ;buffer for "last" number
FibB db 1,99 DUP(0) ;buffer for "previous" number
digits dd 1 ;number of digits in last number
Fibnum dd 2 ;F number
.code
; The two working buffers FibA and FibB will be alternating
; as the last and previous Fibonacci numbers.
; They both start at 1.
; The numbers are kept in lil-endian mode for ease of processing.
start:
mov esi,offset FibA ;ESI will be always pointing to the "last" number
mov edi,offset FibB ;EDI will be always pointing to the "previous" number
start1:
mov ecx,digits ;use as counter for number of additions
xor edx,edx ;offset into the two numbers
start2:
mov al,[esi+edx] ;get digit of last number
adc al,[edi+edx] ;add to it digit of previous number + carry
aaa ;adjust after addition
mov [edi+edx],al ;overwrite previous number with new addition result
inc edx ;point to next digits
dec ecx ;adjust counter
jnz start2 ;continue until last digits added
.if CARRY? ;if addition of last digit has a carry
mov byte ptr [edi+edx],1
inc digits ;adjust the count of digits
.endif
inc Fibnum ;Fn
xchg esi,edi ;switch the pointers so ESI points to "last" number
; and edi points to "previous" number
cmp digits,100
jb start1 ;continue until target quantity of digits is reached
; prepare ascii representation of last number in buffer of previous number
mov ecx,100-4 ;pointing to the start of the last 4 digits
@@:
mov eax,[esi+ecx] ;get 4 bytes
add eax,30303030h ;convert the 4 bytes to ascii
bswap eax
stosd
sub ecx,4
jnc @B
mov byte ptr [edi],0 ;terminate with ending 0 for display
;do whatever you want with the ascii answer
;you may also want to convert to ascii and display its Fn
invoke ExitProcess,0
end start
Hello raymond thank you very much. I think the last correct number from that list is 14787220707439219840 (the third number to the right from the one you mentioned ). But the others are, indeed wrong :icon_redface:. Thanks for telling me that and for your help with that code. I will study the code soon as i can.
:icon14:
QuoteI think the last correct number from that list is 14787220707439219840
I may disagree.
Use paper and pencil and try them from the last one I mentioned.
Quote from: jack on July 07, 2018, 04:04:17 AM
Quote from: daydreamer on July 07, 2018, 03:05:31 AM
the question is does there exist something similar algo for fibonacci,that exist an alternative x! algo for approximation of high numbers
there's a closed form formula for Fibonacci numbers, F(n) = (((1+sqrt(5))*(1/2))^n-((1-sqrt(5))*(1/2))^n)/sqrt(5) https://en.wikipedia.org/wiki/Fibonacci_number#Closed-form_expression
thanks
Ok now i see. After you told me about the error, i just added the number 12200160415121876738 with the number 1293530146158671551. Then to the result 13493690561280548289 (which is correct) i added the previous number (1293530146158671551) and i got as a result the number 14787220707439219840 which is correct too. After that the results were wrong. But now i see you were right, because adding the number 12200160415121876738 with the previous number in the serie (7540113804746346429) is not 1293530146158671551. :idea:
So, indeed the last one correct produced by the program i wrote was 12200160415121876738 as you mentioned. Thank you very much again. :icon14:
xadd is a perfect instruction to calculate Fibonacci numbers.
; Fibonacci numbers using the "xadd" instruction
mov ecx,12 ; term of the Fibonacci sequence
mov eax,0 ; first number
mov edx,1 ; second number
Fibonacci_LP: ; calculate a Fibonacci number with 2 instructions
xadd eax,edx ; exchange and add
loop Fibonacci_LP
; eax = 144
Nice siekmanski :icon14:. But i find the name of the instruction a little misleading since what it supposed to do is:
Quote
Temporary = Source + Destination;
Source = Destination;
Destination = Temporary;
So maybe a good name for the instruction will be: "add and exchange". :idea:
If we exchange and then we add we have eax=1 forever... :dazzled:
temporary=destination;
destination=source;
source=temporary;
destination=source+destination;
Should we report this to intel? :P
What do you think? :biggrin:
I think, the operation goes like this:
Temp = Source
Source = Destination ; Exchange
Destination = Destination + Temp ; Add
:biggrin:
This fibonnaci numbers, task seems to be used often in programming classes,so this thread would be a gem for students felipe :t
Curious why you got the idea to start program fibonnaci?, earlier experience from school,or just randomly picked project?
Wonder if it's possible to use two or more calculations, first calculate starts from the very beginning in one part of xmm register second one in second part of xmm reg starts with big fibonnaci number about in the middle of 32bit integer range?
Siekmanski of course, you are a genius! :biggrin: If you can improve algorithms then you can improve code surely. :t
Magnus i was inspired from a video on youtube about mathematics (I think the name of the documentary is "the mystery of mathematics") :idea:.
I had before saw the fibonacci algorithm in some book, some 2 years before (approximately) like an interesting exercise. It was no more than the operation with the add and exchange (well, exchange and add :biggrin:), but using 16 bits registers. I think the name of the book is something like "assembly programming for the ibm pc" or similar :P.
I was thinking also (in the moment of writing this) in write something using a file :idea:.
I still don't learn almost anything about sse instruction sets :redface:.
math is fun.
But how many primes are in the fibonacci sequence? :P
Nice little exercise felipe!
I only tried the 32 bit version as I am anti-64 bit (anti change) lol.
Just for kicks, I fired up Windows 10-64 and ran the 64 bit version.
Have you made changes to ensure better accuracy? Siekmanski has some really good ideas.
Infinities of them... :biggrin:
Zedd maybe you should try to make a mix of the raymond algorithm (used in part by jimg too) and mine (or jimg if you want to put the results in the console and not in a file) :idea:. How about that math challenge? :icon14:
What i really like of raymond suggested algorithm is that you can reach long size numbers, which looks funny :icon14:.
As you can see with what i wrote the numbers in some point (not to far from the start) overflow the registers, so the next numbers in the sequence are not correct :idea:.
I'll leave that to the math/algebra experts felipe. Maybe Magnus can come up with something. He's always popping up with suggestions but not posting any code. Come on Magnus, show us what you got. :biggrin:
Hi,
Back in February of 2010, I posted a Fibonacci number program
in the 16-bit subforum. It used the BCD opcodes to generate
numbers up to 72 digits. More of a learning excursion than
anything else. Had to make the BCD instructions work as intended.
Cheers,
Steve N.
Not sure what you are asking for.
Here is where I quit playing around, writes to console.
Absolutely accurate. Just set max size to whatever you want.
Thats pretty good, Jim.
I printed it to text using ec.exe > fibo.txt
its right aligned so you have to scroll to the right. Open with qeditor works well.
ends with F954 and length of that string is 200 characters.
Nice clear, concise code. Heres a disassembly of the code using olly...
00401000 e>/$ 6A F5 PUSH -0B ; /DevType = STD_OUTPUT_HANDLE
00401002 |. E8 25010000 CALL <JMP.&kernel32.GetStdHandle> ; \GetStdHandle
00401007 |. A3 70324000 MOV DWORD PTR DS:[403270],EAX ; kernel32.BaseThreadInitThunk
0040100C |. 6A 00 PUSH 0 ; /pOverlapped = NULL
0040100E |. 68 74324000 PUSH ec.00403274 ; |pBytesWritten = ec.00403274
00401013 |. 68 CB000000 PUSH 0CB ; |nBytesToWrite = CB (203.)
00401018 |. 68 00304000 PUSH ec.00403000 ; |Buffer = ec.00403000
0040101D |. FF35 70324000 PUSH DWORD PTR DS:[403270] ; |hFile = NULL
00401023 |. E8 10010000 CALL <JMP.&kernel32.WriteFile> ; \WriteFile
00401028 |. 6A 00 PUSH 0 ; /pOverlapped = NULL
0040102A |. 68 74324000 PUSH ec.00403274 ; |pBytesWritten = ec.00403274
0040102F |. 68 CB000000 PUSH 0CB ; |nBytesToWrite = CB (203.)
00401034 |. 68 CC304000 PUSH ec.004030CC ; |Buffer = ec.004030CC
00401039 |. FF35 70324000 PUSH DWORD PTR DS:[403270] ; |hFile = NULL
0040103F |. E8 F4000000 CALL <JMP.&kernel32.WriteFile> ; \WriteFile
00401044 |. 60 PUSHAD
00401045 |. 8D35 00304000 LEA ESI,DWORD PTR DS:[403000]
0040104B |. 8D3D CC304000 LEA EDI,DWORD PTR DS:[4030CC]
00401051 |. 8D2D 98314000 LEA EBP,DWORD PTR DS:[403198]
00401057 |. C705 78324000 03000000 MOV DWORD PTR DS:[403278],3
00401061 |> B9 C8000000 /MOV ECX,0C8
00401066 |. C605 7C324000 00 |MOV BYTE PTR DS:[40327C],0
0040106D |> B8 00000000 |/MOV EAX,0
00401072 |. 8A0431 ||MOV AL,BYTE PTR DS:[ECX+ESI]
00401075 |. 8A1439 ||MOV DL,BYTE PTR DS:[ECX+EDI]
00401078 |. 3C 20 ||CMP AL,20
0040107A |. 75 02 ||JNZ SHORT ec.0040107E
0040107C |. B0 30 ||MOV AL,30
0040107E |> 02C2 ||ADD AL,DL
00401080 |. 0205 7C324000 ||ADD AL,BYTE PTR DS:[40327C]
00401086 |. 2C 30 ||SUB AL,30
00401088 |. C605 7C324000 00 ||MOV BYTE PTR DS:[40327C],0
0040108F |. 3C 39 ||CMP AL,39
00401091 |. 76 09 ||JBE SHORT ec.0040109C
00401093 |. C605 7C324000 01 ||MOV BYTE PTR DS:[40327C],1
0040109A |. 2C 0A ||SUB AL,0A
0040109C |> 880429 ||MOV BYTE PTR DS:[ECX+EBP],AL
0040109F |. 49 ||DEC ECX
004010A0 |. 74 72 ||JE SHORT ec.00401114
004010A2 |. 803C39 20 ||CMP BYTE PTR DS:[ECX+EDI],20
004010A6 |. 75 0F ||JNZ SHORT ec.004010B7
004010A8 |. 803D 7C324000 00 ||CMP BYTE PTR DS:[40327C],0
004010AF |. 74 04 ||JE SHORT ec.004010B5
004010B1 |. C60429 31 ||MOV BYTE PTR DS:[ECX+EBP],31
004010B5 |> EB 02 ||JMP SHORT ec.004010B9
004010B7 |>^ EB B4 |\JMP SHORT ec.0040106D
004010B9 |> 6A 00 |PUSH 0 ; /pOverlapped = NULL
004010BB |. 68 74324000 |PUSH ec.00403274 ; |pBytesWritten = ec.00403274
004010C0 |. 68 C9000000 |PUSH 0C9 ; |nBytesToWrite = C9 (201.)
004010C5 |. 55 |PUSH EBP ; |Buffer = 0012FF94
004010C6 |. FF35 70324000 |PUSH DWORD PTR DS:[403270] ; |hFile = NULL
004010CC |. E8 67000000 |CALL <JMP.&kernel32.WriteFile> ; \WriteFile
004010D1 |. FF35 78324000 |PUSH DWORD PTR DS:[403278] ; /<%li> = 0
004010D7 |. 68 61324000 |PUSH ec.00403261 ; |Format = " %li\r\n"
004010DC |. 68 7D324000 |PUSH ec.0040327D ; |s = ec.0040327D
004010E1 |. E8 58000000 |CALL <JMP.&user32.wsprintfA> ; \wsprintfA
004010E6 |. 83C4 0C |ADD ESP,0C
004010E9 |. 6A 00 |PUSH 0 ; /pOverlapped = NULL
004010EB |. 68 74324000 |PUSH ec.00403274 ; |pBytesWritten = ec.00403274
004010F0 |. 50 |PUSH EAX ; |nBytesToWrite = 779E3C33 (2006858803.)
004010F1 |. 68 7D324000 |PUSH ec.0040327D ; |Buffer = ec.0040327D
004010F6 |. FF35 70324000 |PUSH DWORD PTR DS:[403270] ; |hFile = NULL
004010FC |. E8 37000000 |CALL <JMP.&kernel32.WriteFile> ; \WriteFile
00401101 |. 8BC6 |MOV EAX,ESI
00401103 |. 8BF7 |MOV ESI,EDI
00401105 |. 8BFD |MOV EDI,EBP
00401107 |. 8BE8 |MOV EBP,EAX ; kernel32.BaseThreadInitThunk
00401109 |. FF05 78324000 |INC DWORD PTR DS:[403278]
0040110F |.^ E9 4DFFFFFF \JMP ec.00401061
00401114 |> 61 POPAD
00401115 |. 68 A0860100 PUSH 186A0 ; /Timeout = 100000. ms
0040111A |. E8 13000000 CALL <JMP.&kernel32.Sleep> ; \Sleep
0040111F |. 6A 00 PUSH 0 ; /ExitCode = 0
00401121 \. E8 00000000 CALL <JMP.&kernel32.ExitProcess> ; \ExitProcess
Thats the disassembly from olly. Looks like it could easily be modified to write directly to file if needed.
heres the printout of the first 100 (I removed the right alignment, to save space here)
0 0
1 1
1 2
2 3
3 4
5 5
8 6
13 7
21 8
34 9
55 10
89 11
144 12
233 13
377 14
610 15
987 16
1597 17
2584 18
4181 19
6765 20
10946 21
17711 22
28657 23
46368 24
75025 25
121393 26
196418 27
317811 28
514229 29
832040 30
1346269 31
2178309 32
3524578 33
5702887 34
9227465 35
14930352 36
24157817 37
39088169 38
63245986 39
102334155 40
165580141 41
267914296 42
433494437 43
701408733 44
1134903170 45
1836311903 46
2971215073 47
4807526976 48
7778742049 49
12586269025 50
20365011074 51
32951280099 52
53316291173 53
86267571272 54
139583862445 55
225851433717 56
365435296162 57
591286729879 58
956722026041 59
1548008755920 60
2504730781961 61
4052739537881 62
6557470319842 63
10610209857723 64
17167680177565 65
27777890035288 66
44945570212853 67
72723460248141 68
117669030460994 69
190392490709135 70
308061521170129 71
498454011879264 72
806515533049393 73
1304969544928657 74
2111485077978050 75
3416454622906707 76
5527939700884757 77
8944394323791464 78
14472334024676221 79
23416728348467685 80
37889062373143906 81
61305790721611591 82
99194853094755497 83
160500643816367088 84
259695496911122585 85
420196140727489673 86
679891637638612258 87
1100087778366101931 88
1779979416004714189 89
2880067194370816120 90
4660046610375530309 91
7540113804746346429 92
12200160415121876738 93
19740274219868223167 94
31940434634990099905 95
51680708854858323072 96
83621143489848422977 97
135301852344706746049 98
218922995834555169026 99
354224848179261915075 100
Now we need a sieve to test for prime :icon_mrgreen:
Then we end up with a fibo-prime listing. 8)
With a slight modification to jimg's code we can assemble using qeditor "console assemble and link"
include \masm32\include\windows.inc
uselib Macro libname:req
include \masm32\include\libname.inc
includelib \masm32\lib\libname.lib
Endm
Helps for when you don't have WinAsm installed.
I tried it with maxsize=2000 :biggrin:
later :
But it only printed out up to char length=1000, F=4782 :( <-- nevermind, I forgot to assemble & link. It works perfectly
:t
for maxsize=10000, filesize is 456 MB :shock:
still waiting to read file into qeditor. 8)
for maxsize=10000, F=47847 Thats a long number.
I won't post it here though. ;)
in qeditor, the maximum line length appears to be 3071 chars (probably the limits of the rich edit control) so the results for maxsize=10000
are split into four lines. I won't check it manually for accuracy, I'll just have to trust the algo. :P
I can see some benchmark tests over the horizon for the fastest fibonacci algo. :biggrin:
I just installed (again) Windows 7 64 bit, now might be a good time to try coding with ml64. :icon_mrgreen:
Now I remember where I did something similar. It never really worked out though. ascii adder (http://masm32.com/board/index.php?topic=4641.msg49882#msg49882)
It was supposed to read strings of ascii numbers (not hex)
Then add them together. I tried to recall yesterday, but memory fails.
I should have made the program strip the leading zeros, but I have a little proggy that can do that...
include \masm32\include\masm32rt.inc
OpenFilex proto :dword
SaveFilex proto :dword
LoadFilex proto :dword
WriteFilex proto :dword, :dword, :dword
zStrLen proto :dword
.data
str1 dd 0
str2 dd 0
hWnd dd 0
hInstance dd 0
infile db 128 dup (0)
outfile db 128 dup (0)
inbuf dd 0
insize dd 0
.code
start:
invoke OpenFilex, addr infile
invoke LoadFilex, eax
mov inbuf, esi
mov insize, ecx
xor eax, eax
xor edx, edx
top1:
mov cl, byte ptr [esi+edx]
cmp cl, 0
jz done1
cmp cl, "0"
jnz writeit
iszero:
cmp byte ptr [esi+edx], "0"
jnz writeit
inc edx
jmp iszero
writeit:
mov cl, byte ptr [esi+edx]
cmp cl, 0Dh
jz crlf1
mov byte ptr [esi+eax], cl
inc eax
inc edx
cmp edx, insize
jge done1
jmp writeit
crlf1: ; special case, write two bytes
mov byte ptr [esi+eax], cl
inc eax
inc edx
cmp edx, insize
jge done1
mov cl, byte ptr [esi+edx]
mov byte ptr [esi+eax], cl
inc eax
inc edx
cmp edx, insize
jge done1
jmp top1
done1:
mov byte ptr [esi+eax], 0
invoke zStrLen, esi
push eax
push esi
invoke SaveFilex, addr outfile
pop esi
pop eax
invoke WriteFilex, addr outfile, esi, eax
invoke GlobalFree, inbuf
invoke ExitProcess, 0
OpenFilex proc FileBuffer:DWORD
LOCAL ofn:OPENFILENAME
.data
lpOpen db "Open File", 0
lpSave db "Save File", 0
lpFilter db "All Files", 0, "*.*", 0, 0
.code
mov eax, FileBuffer
mov BYTE PTR [eax], 0
push edi
mov ecx, sizeof OPENFILENAME
mov al, 0
lea edi, ofn
rep stosb
pop edi
mov ofn.lStructSize, sizeof OPENFILENAME
m2m ofn.hWndOwner, hWnd
m2m ofn.hInstance, hInstance
m2m ofn.lpstrFilter, offset lpFilter
m2m ofn.lpstrFile, FileBuffer
mov ofn.nMaxFile, 240h
m2m ofn.lpstrTitle, offset lpOpen
mov ofn.Flags, OFN_EXPLORER or OFN_FILEMUSTEXIST or OFN_LONGNAMES
invoke GetOpenFileName,ADDR ofn
mov eax, FileBuffer
ret
OpenFilex endp
SaveFilex proc FileBuffer:DWORD
LOCAL ofn:OPENFILENAME
mov eax, FileBuffer
mov BYTE PTR [eax], 0
push edi
mov ecx, sizeof OPENFILENAME
mov al, 0
lea edi, ofn
rep stosb
pop edi
mov ofn.lStructSize, sizeof OPENFILENAME
m2m ofn.hWndOwner, hWnd
m2m ofn.hInstance, hInstance
m2m ofn.lpstrFilter, offset lpFilter
m2m ofn.lpstrFile, FileBuffer
mov ofn.nMaxFile, 240h
m2m ofn.lpstrTitle, offset lpSave
mov ofn.Flags, OFN_EXPLORER or OFN_LONGNAMES or OFN_HIDEREADONLY or OFN_OVERWRITEPROMPT
invoke GetSaveFileName,ADDR ofn
mov eax, FileBuffer
ret
SaveFilex endp
LoadFilex proc lpName:DWORD
LOCAL hFile:DWORD, fl:DWORD, bRead:DWORD, hMem$:DWORD
invoke CreateFile,lpName,080000000h,1,NULL,3,NULL,NULL
cmp eax, -1
jne @F
fn MessageBox,NULL,lpName,"Couldn't read File!",MB_OK
xor eax, eax
ret
@@:
mov hFile, eax
invoke GetFileSize,hFile,NULL
mov fl, eax
invoke GlobalAlloc, GPTR, fl
mov hMem$, eax ; source file memory
invoke ReadFile,hFile,hMem$,fl,ADDR bRead,NULL
invoke CloseHandle,hFile
mov eax, 1
mov esi, hMem$
mov ecx, fl
ret
LoadFilex endp
WriteFilex proc lpName:DWORD,lpData:DWORD,fl:DWORD
LOCAL hOutput:DWORD
LOCAL bw :DWORD
invoke CreateFile,lpName,GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL
cmp eax, -1
jne @F
fn MessageBox,NULL,lpName,"Couldn't Write File!",MB_OK
xor eax, eax
ret
@@:
mov hOutput, eax
invoke WriteFile,hOutput,lpData,fl,ADDR bw,NULL
invoke FlushFileBuffers,hOutput
invoke CloseHandle,hOutput
mov eax, 1
ret
WriteFilex endp
zStrLen proc src:dword
push esi
push ecx
mov esi, src
xor eax, eax
@@:
mov cl, [esi]
cmp cl, 0
jz @f
inc eax
inc esi
jmp @b
@@:
pop ecx
pop esi
ret
zStrLen endp
end start
The only caveat with this program, it strips the very first zero, which is in fact supposed to be part of the Fibonacci sequence. :(
I'll look at that when time permits.
here's something you may not have known about the Fibonacci sequence https://www.futilitycloset.com/2015/06/28/made-to-order-4/
see also http://www.flyingcoloursmaths.co.uk/ask-uncle-colin-is-the-fibonacci-series-witchcraft/
Quote from: jack on July 28, 2018, 03:24:47 AM
here's something you may not have known about the Fibonacci sequence...
Wow! That is so cool, Jack. Who would have thunk?
Thanks for the links. :t
I think I'm going to need a better calculator to check the results. :lol:
here's another Fibonacci Related Link (https://joedubs.com/fibonacci-fun/)
I don't believe
everything I read on the internet, but it has entertainment value.
The Fibonacci sequence in my view was designed to tell the progression of rabbits, how many rabbits would be born. But looking better at nature, we can see paternities such as trees. The trees when they are growing have only one branch, then over the years if we imagine an imaginary horizontal line from the first branch we will have two, and so on. Fibonacci responds to some branches of trees.
Small addition to my fibonacci generator. We now have the leading zeroes/spaces removed.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; ;-------------------------------------------------------------------------------;;
;; ; Program to output a Fibonacci sequence of any length in the command window ;;
;; ;;; ---- can also print to file: "fiboz.exe > fibonacci.txt" ;;
;; ;-------------------------------------------------------------------------------;;
;; ; following the forumla "F = (F-1) + (F-2)" ;;
;; ;----------------------------------------- ;;
;; ; where F is the Fibonacci number being calculated ;;
;; ; F-1 is the Fibonacci number just before that ;;
;; ; F-2 is the Fibonacci number before F-1 ;;
;; ;-------------------------------------------------------------------------------;;
;; ; credits: jimg for an excellent algo, ;;
;; ; felipe for inspiring me to finish my 'ascii adder' routine ;;
;; ;-------------------------------------------------------------------------------;;
;; ; Fair Warning! The output file can get extremely large very fast! ;;
;; ; example for finacci final length of 58000 the output file was ;;
;; ; 7.49 GB is size! And that is with the leading zeroes/ spaces removed! ;;
;; ;-------------------------------------------------------------------------------;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
include \masm32\include\masm32rt.inc
ascii_adder proto :dword, :dword, :dword, :dword
TrimZero proto :dword, :dword
.data
maxsize dd 100 ; max length of fibonacci string
pval1 dd 0
pval2 dd 0
pval3 dd 0
tmpbuf dd 0
ctrx dd 0
.code
Program:
pushad
inc maxsize ; for auto zero termination
invoke GlobalAlloc, GPTR, maxsize
mov pval1, eax
invoke GlobalAlloc, GPTR, maxsize
mov pval2, eax
invoke GlobalAlloc, GPTR, maxsize
mov pval3, eax
invoke GlobalAlloc, GPTR, maxsize ; <-- extra buffer added for the procedure
mov tmpbuf, eax ; --- that removes the leading zeros.
dec maxsize ; reset maxsize to original
mov esi, pval1 ; previous val
mov edi, pval2 ; previous val
mov ebx, pval3 ; new val
xor ecx, ecx
@@:
mov byte ptr [esi+ecx], 30h ; fill the buffers with "0"
mov byte ptr [edi+ecx], 30h
mov byte ptr [ebx+ecx], 30h
inc ecx
cmp ecx, maxsize ; loop til buffers filled
jnz @b
mov byte ptr [edi+ecx-1], 31h ; insert the first digit otherwise we will be adding '0+0' lol
mov esi, pval1 ; put the buffer addresses into registers
mov edi, pval2
mov ebx, pval3
above:
invoke ascii_adder, esi, edi, ebx, maxsize ; call my little proc :)
mov eax, esi ; jimg's switcherooo register voodoo
mov esi, edi
mov edi, ebx
mov ebx, eax
cmp ctrx, 0 ; check if this counter is zero, if so we keep the ascii "0"
jz @f ; all other fibonacci strings wil have the leading zeros removed.
push ebx
invoke TrimZero, ebx, tmpbuf
print tmpbuf, 0Dh, 0Ah
pop ebx
jmp ahead
@@:
inc ctrx
print "0", 0Dh, 0Ah ; for the first digit (zero) - otherwise the
; proc that removes leading zeros will erase it.
ahead:
cmp byte ptr [ebx], "0" ; check if we are done
jz above
invoke GlobalFree, pval1 ; free the memory
invoke GlobalFree, pval2
invoke GlobalFree, pval3
invoke GlobalFree, tmpbuf
popad
invoke ExitProcess, 0 ; hasta la vista, baby
ascii_adder proc src1:dword, src2:dword, dst:dword, lent:dword ; :D
local carrie:dword
push esi
push edi
push ebx
mov esi, src1
mov edi, src2
mov ebx, dst
mov ecx, lent
mov carrie, 0
top:
mov eax,0
mov al,byte ptr [esi+ecx-1]
mov dl,byte ptr [edi+ecx-1]
add al,dl
sub al, 30h
add eax, carrie
mov carrie, 0
cmp al, 39h
jbe @f ; pseudo carry flag
mov carrie, 1
sub al, 10
@@:
mov [ebx+ecx-1], al
dec ecx
cmp ecx, 0
jnz top
pop ebx
pop edi
pop esi
ret
ascii_adder endp
TrimZero proc src:dword, dst:dword ; added this proc to remove leading zeroes.
push esi
push edi
mov esi, src
mov edi, dst
xor eax, eax
xor ecx, ecx
testlin:
mov dl, [esi+eax]
cmp dl, 0
jz done
cmp dl, 0Dh
jz crlf
cmp dl, 0Ah
jz crlf
cmp dl, 30h
jz zero
jmp copyall
zero:
inc eax
mov dl, [esi+eax]
cmp dl, 0
jz done
cmp dl, 30h
jz zero
cmp dl, 0Dh
jz crlf
cmp dl, 0Ah
jz crlf
jmp copyall
crlf:
mov dl, [esi+eax]
mov [edi+ecx], dl
inc eax
inc ecx
mov dl, [esi+eax]
cmp dl, 0
jz done
cmp dl, 30h
jz zero
cmp dl, 0Dh
jz crlf
cmp dl, 0Ah
jz crlf
copyall:
mov dl, [esi+eax]
cmp dl, 0
jz done
cmp dl, 0Dh
jz crlf
cmp dl, 0Ah
jz crlf
mov [edi+ecx], dl
inc eax
inc ecx
jmp copyall
done:
pop edi
pop esi
ret
TrimZero endp
End Program
:biggrin:
Quote from: mineiro on July 28, 2018, 11:31:35 AM
The Fibonacci sequence in my view was designed to tell the progression of rabbits,
Or Humans! :greensml:
tested first with highlevel and I subconciusly unrolled it 2 fibonnaci/loop
I have yet to solve the printmacro
mov eax,cs:fibo1
mov edx,0
mov ebx,cs:fibo2
mov ecx,0
mov esi,0
mov edi,0
mov ebp,0
mov esp,0
loop1:
pmac ;printmacro for 2 fibonacci numbers
add eax,ebx ;32bit
adc edx,ecx ;64bit
adc esi,edi ;96bit
adc ebp,esp ;128bit
;jc l2
add ebx,eax ;unrolled addition
adc ecx,edx
adc edi,esi
adc esp,ebp
; jc l2
dec cs:lvar ;run thru 4giga
jne loop1
;or stop when overflow of 128bit is met
l2: ;abort when overflow has happened
and find right conditional jump to exit loop when overflow happens
I was also thinking about fibonnacci will be not limited by computer memory,keep 2 fibonnaci numbers stored in compressed form for each page you can display in Textarea and make them generate them Just In Time
here is my original code,dont know why I subconciusly unrolled it the first time I made it
program fibonnac
clrhome
1->C
2->D
for(B,0,1000)
Disp B,C,D
D+C->C
C+D->D
end
;end=end of forloop
1->C, is reverse way of type C=1
after 238*2
3.5205211795e99
5.696323923e99 it stopped the program because of overflow
Quote from: daydreamer on August 04, 2018, 02:49:10 AM
1->C, is reverse way of type C=1
Reminds me of TI-Basic. 1-->C, yes. 8)
or 'sto' from another calc. :P
I never did understand fully, 'for' loops, and exactly how they work.
.ifs and .whiles are easy. How would a 'for' loop translate to asm?
Hi,
Quote from: zedd151 on August 05, 2018, 04:28:08 PM
I never did understand fully, 'for' loops, and exactly how they work.
.ifs and .whiles are easy. How would a 'for' loop translate to asm?
Well, for a "FOR" loop up to a few thousand, the following code
is roughly what would work.
; FOR X = 1 TO 9
;data
Xvar DW ?
;code
MOV [Xvar],1 ; Top of loop
ForLab:
; Your code? It can use Xvar, but not change it.
INC [Xvar]
CMP WORD PTR [Xvar],9
JB ForLab ; End of loop
HTH,
Steve N.
Edit
Correction JNZ => JB , it would have terminated at 8.
Added usage comment.
SRN
Thanks Steve, that is pretty simple code, just the way I like it. :t
I have seen the notation, 'for i, 1, x' or something similar but never really 'got it' :icon_confused:
I probably write 'for' loops all the time without knowing they are 'for' loops. 8)
Binet's formula (http://e-maxx.ru/tex2png/cache/1094df5457848414456a232b8e0e0254.png) and fast exponentiation
N equ 26
.data
buffer db 50 dup(?)
format db "%u",0
caption db "Fibonacci",0
const0_5 dd 0.5
k dd ?
inverse_square_root_from_five dd 0.44721359549995793928183473374626;=1/sqrt(5)
x dd 1.6180339887498948482045868343656;=(1+sqrt(5))/2
.code
start: fninit
fld inverse_square_root_from_five ;st=0.44721359549995793928183473374626
fld x ;st=1.6180339887498948482045868343656
mov ecx,N+1 ;st=1.618 st(1)=0.44721
@@: test ecx,1
jz a1
fmul st(1),st
a1: fmul st,st
shr ecx,1
jnz @b
fstp st
fistp k ;k=int(((1.62)^N)/sqrt(5))
invoke wsprintf,addr buffer,addr format,k
add esp,4*3
invoke MessageBox,0,addr buffer,addr caption,MB_OK
invoke ExitProcess,NULL
end start
Looks very fast mikl
Zedd, forloop is so BASIC loop
Assembly its seem more common with countdown to zero loops dec/sub loop counter+ jne loop
Loops with fixed iteration counts vary only at which end the evaluation takes place.
Bottom evaluate
lbl0:
; do something
sub cntr, 1
jnz lbl0 ; <<<< fixed here. :redface:
Top evaluate
jmp evalhere
lbl1:
; do something
evalhere:
sub cntr, 1
jnz lbl1
Quote from: hutch-- on August 07, 2018, 01:14:58 PM
Bottom evaluate
lbl0:
; do something
sub cntr, 1
jnz lbl1 >-------->
|
|
Top evaluate |
|
jmp evalhere |
lbl1: <--------------<
; do something
evalhere:
sub cntr, 1
jnz lbl1
Must be late in the day. :icon_mrgreen:
Apparently I write 'for' loops all the time, without knowing they are 'for' loopz.
I have been moving away from using '.if' blocks as well, (unless a fairly complex statement) I prefer manually coding the jumps, etc.
for i, 1, 10 yuk. ::)
.if blocks come into their own when you have to have nested conditional testing, it can be done with compares, jumps and labels but it becomes very messy with multiple depth testing as you need to be very creative with the number of unique labels you need to use.
Quote from: hutch-- on August 07, 2018, 01:14:58 PM
Loops with fixed iteration counts vary only at which end the evaluation takes place.
Bottom evaluate
lbl0:
; do something
sub cntr, 1
jnz lbl0 ; <<<< fixed here. :redface:
Top evaluate
jmp evalhere
lbl1:
; do something
evalhere:
sub cntr, 1
jnz lbl1
but whats best for innerloop counters/outerloop counters?, I have seen examples using ecx for both,with help of push/pop
and 8bits you had very few registers,so dec/inc memory location was used sometimes,especially 6502,because its way of indirect adressing
or the use of one long innerloop,with AND 1023 to get x coordinate in a 1024'768 resolution or 1024*1024 texture
zedd:forloop could as well be a while not zero etc coded in High language and compiler produces the same code in assembler
Magnus,
You should know the answer to simple stuff like this. Use a register if you can, a memory operand if you can't. If you have to choose, use the register for the loop that gets hit the hardest which in your case is the inner loop but also remember that there are far more loop designs than simple nested loops, try multi cross fire loops.
Quote from: daydreamer on August 07, 2018, 09:30:16 PMI have seen examples using ecx for both,with help of push/pop
Like this? Attention, if you have more than ten million iterations or so, it might be a bit slower than using a register...
include \masm32\include\masm32rt.inc
.code
start:
loopsrequested=20
push loopsrequested-1
.Repeat
print "*"
dec dword ptr [esp]
.Until Sign?
pop edx
inkey " - that was easy, right?"
exit
end start