flat assembler
Message board for the users of flat assembler.

Index > High Level Languages > factorial implementation

Goto page Previous  1, 2
Author
Thread Post new topic Reply to topic
Akujin



Joined: 11 Oct 2011
Posts: 26
Location: Exile
Akujin 05 Nov 2011, 22:27
Quick test using 80bit globals...
Code:
; DATA
; user number
num dt 100.0
; result
fac dt 0.0

; CODE
factnr:
; ...
     fld1
        fstp [fac]
redof:
    fld [num]
   fld1
        fcomip st,st1
       jae donef
   fld st                  
    fld1
        fsubp
       fstp [num]
  fld [fac]
   fmulp
       fstp [fac]
  jmp redof
donef: 
    fstp st
; ...
    ret
    

...

_________________
CLI
HLT
Post 05 Nov 2011, 22:27
View user's profile Send private message Visit poster's website Reply with quote
typedef



Joined: 25 Jul 2010
Posts: 2909
Location: 0x77760000
typedef 06 Nov 2011, 06:50
nicef codef Akujinf

lolf
Post 06 Nov 2011, 06:50
View user's profile Send private message Reply with quote
Andy



Joined: 17 Oct 2011
Posts: 55
Andy 06 Nov 2011, 18:29
I must admit the code looks good(maybe if you could explain the lines for a beginer would be awesome) and is very short(I like that) but I'm confused about how to get OP codes. As I said I don't use real FASM instructions in my program, just the binary code produced. I tried to put this code in 8086 emulator but returned me a lot of 00 bytes. I will try to run the code with FASM Library from my HLL and I come back with the result. Thank you.
Post 06 Nov 2011, 18:29
View user's profile Send private message Reply with quote
Akujin



Joined: 11 Oct 2011
Posts: 26
Location: Exile
Akujin 06 Nov 2011, 19:48
The code need at least a PPRO due to fcomip
can be changed tough!

Short code? this is short code! Twisted Evil ...
Code:
factnr:
   fld1
        fild dword[esp+4]       ;arg1
redof:
 fld1
        fcomip st,st1   ;!
  jae exit1       ;!
  fld st                  
    fld1
        fsubp
       fxch
        fmulp st2,st
        jmp redof
exit1: 
    fstp st
     ; result on st0
     ret 4           ;!
    


Usage:
Code:
push 50   ; DWORD
call factnr
;st0=result
fstp [some 80bit var]
    


To understand the code use a debugger like Ollydbg, step trough the code
and watch in the CPU/FPU panel what is happening, is the best comment system.
To get OP codes use FASM bin output

Regards.

_________________
CLI
HLT
Post 06 Nov 2011, 19:48
View user's profile Send private message Visit poster's website Reply with quote
Andy



Joined: 17 Oct 2011
Posts: 55
Andy 07 Nov 2011, 21:18
I have some kind of problem, I made a file with the code you provide me above and compile it with fasm. Until now, no errors. I tried to run the executable but I cannot, it says the exe is valid but cannot run on x64 and if I try to open it with ollydgb to get the opcode I got an error too. Confused Can I force to compile for x86 or something to avoid these errors?

regards
Post 07 Nov 2011, 21:18
View user's profile Send private message Reply with quote
Akujin



Joined: 11 Oct 2011
Posts: 26
Location: Exile
Akujin 07 Nov 2011, 22:11
Use Ollydbg to run this x86 app.


Description: factorial sample
Download
Filename: fact.7z
Filesize: 868 Bytes
Downloaded: 871 Time(s)


_________________
CLI
HLT
Post 07 Nov 2011, 22:11
View user's profile Send private message Visit poster's website Reply with quote
Andy



Joined: 17 Oct 2011
Posts: 55
Andy 08 Nov 2011, 11:54
Thanks, your executable gives me no errors but I think I too stupid to figure this out. I got as result 4 for Factorial(7). This is the opcode I got from OllyDbg. Actually I'm not sure if I know very well how to use OllyDbg but if I don't get any program crash it means the code is good, but why I get 4 instead of 5040, I don't know. Any idea?

Code:
"0xD9E8DB442404D9E8DFF1730CD9C0D9E8DEE9D9C9DECAEBEEDDD8C204006A32E8DCFFFFFFDB3D001040006A00FF1540304000"    


I got no errors when I call this raw code but the result is 4?? Confused

If you're interesed about how I call the code, here is the code:
Code:
#include <Memory.au3>

$iNumber = 7
MsgBox(0,"",Factorial($iNumber))

Func Factorial($iNumber)
   $bCode = "0xD9E8DB442404D9E8DFF1730CD9C0D9E8DEE9D9C9DECAEBEEDDD8C204006A32E8DCFFFFFFDB3D001040006A00FF1540304000"
 $iSize = BinaryLen($bCode)
  $pBuffer = _MemVirtualAlloc(0,$iSize,$MEM_COMMIT,$PAGE_EXECUTE_READWRITE)
   $tBuffer = DllStructCreate("byte[" & $iSize & "]",$pBuffer)
     DllStructSetData($tBuffer,1,$bCode)
 $aRet = DllCallAddress("int",$pBuffer,"int",$iNumber)
   _MemVirtualFree($pBuffer,$iSize,$MEM_RELEASE)
       If IsArray($aRet) Then
              Return $aRet[0]
     Else
                Return "ERROR"
    EndIf
EndFunc    
Post 08 Nov 2011, 11:54
View user's profile Send private message Reply with quote
goldenspider



Joined: 16 May 2011
Posts: 38
goldenspider 17 Nov 2011, 13:23
my poor code,you can optimize it.
Code:
format PE console
entry start

include 'win32a.inc'
include 'MACRO\if.inc'
;---------------------------------------------
section '.text' code readable executable

 start:
    invoke  printf,inform
    mov     eax,[dwStrlen]
    shl     eax,2
    mov     [dwStrlen],eax
    invoke  malloc,eax
    mov     [lpOutBuf],eax
@@:
    cinvoke  memset,[lpOutBuf],0,[dwStrlen]
    mov     esi,[lpOutBuf]
    mov     dword [esi],1
   
    stdcall  _Input
    stdcall  _OutPut,[lpOutBuf],eax
    jmp     @B

;========================================     
proc _Factorial uses ebx esi,lpA:dword,N:dword
local @c:DWORD,@len:DWORD

    mov [@len],1
    mov esi,[lpA]
    cmp [N],0
    je  .EXIT
.Loop1:
    mov  [@c],0
    xor  ebx,ebx
  @@:
    mov  eax,[esi+ebx*4]
    imul eax,[N]
    add  eax,[@c]
    
    cdq
    mov  ecx,10000
    idiv ecx
    mov  [esi+ebx*4],edx
    mov  [@c],eax

    inc ebx
    cmp ebx,[@len]
    jb  @B

    mov [esi+ebx*4],eax
    cmp eax,0
    jbe .A00
    inc [@len]
.A00:
    dec [N]
    cmp [N],1
    ja  .Loop1
.EXIT:    
    mov eax,[@len]
    ret
endp
;========================================
proc _Input uses ebx 
     local @num:DWORD
     mov [@num],0
  @@:
     cinvoke getchar
     mov ebx,eax
     
     .if ebx ='q' | ebx ='Q'
        cinvoke exit,0
     .elseif ebx >= '0' & ebx <= '9'
        mov  ecx,[@num]
        imul ecx,10
        sub  ebx,'0'
        add  ecx,ebx
        mov  [@num],ecx
     .elseif ebx=0ah
        mov  eax,[@num]
        ret
     .endif
     jmp @B
endp
;========================================
proc _OutPut uses esi,lpBuf:dword,@num:dword
    stdcall _Factorial,[lpBuf],[@num]
    dec     eax
    push    eax
    push    esi
    mov     esi,[lpBuf]
    
    cinvoke printf,fmt0,[@num],dword [esi+eax*4]
    pop     esi
    pop     eax
    test    eax,eax
    jz      .exit
    dec     eax
 @@:
    push    eax
    push    esi
    cinvoke printf,fmt1,dword [esi+eax*4]
    pop     esi
    pop     ax
    dec     eax
    jns     @B   
.exit:
    cinvoke  printf,fmt2
    xor     eax,eax
    ret
endp
;========================================
section '.data' data readable writeable
    fmt0     db  '%d! = %d',0
    fmt1     db  '%04d',0
    fmt2     db  0dh,0ah,0
    inform   db  'Please input  num (0~9999) Or q-exit:',0dh,0ah,0
    dwStrlen dd  8916
    lpOutBuf dd  ?
;---------------------------------------------
section '.idata' import data readable writeable
  library msvcrt,'msvcrt.dll'

  import msvcrt,\
     printf,'printf',\
     getchar,'getchar',\
     malloc,'malloc',\
     memset,'memset',\
     exit,'exit'    
Post 17 Nov 2011, 13:23
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20453
Location: In your JS exploiting you and your system
revolution 17 Nov 2011, 13:34
goldenspider: Did you try "12!"?

Your code: 47900
Actual 12!: 479001600
goldenspider wrote:
... you can optimize it.
It is too early to optimise it yet.

Standard rule: Get it working, then get it fast.
Post 17 Nov 2011, 13:34
View user's profile Send private message Visit poster's website Reply with quote
goldenspider



Joined: 16 May 2011
Posts: 38
goldenspider 17 Nov 2011, 15:02
Aha,you are right. I just recode c.

Sorry,you can modify line 104:
pop ax => pop eax
Post 17 Nov 2011, 15:02
View user's profile Send private message Reply with quote
Akujin



Joined: 11 Oct 2011
Posts: 26
Location: Exile
Akujin 17 Nov 2011, 22:42
Andy solved the problem in the AutoIt function:
Code:
$aRet = DllCallAddress("int",$pBuffer,"int",$iNumber) 
    

changed to
Code:
$aRet = DllCallAddress("double",$pBuffer,"int",$iNumber) 
    

and added code for negative, 0 and 1 case.


Regards.

_________________
CLI
HLT
Post 17 Nov 2011, 22:42
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page Previous  1, 2

< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.