flat assembler
Message board for the users of flat assembler.

Index > High Level Languages > Need help to convert C code to Fasm

Author
Thread Post new topic Reply to topic
Xerkan



Joined: 22 Dec 2012
Posts: 2
Xerkan 29 Dec 2012, 19:05
Hi
i am new to Fasm ,i found it very useful for creating small DLLs
i have managed to build a simple dll with few functions
but i need help for further steps
i am not going to use it to create complex applications , as it is very hard for me to understand Assembly syntax
i am only going to use it to make wrapper dlls to Windows API functions

i need help with the following function , as you can see that the arguments are pointers to data in caller's state
and this is a two-pass function , first time caller will get the required size of memory and allocate it then second time callee will copy szText to allocated memory

Code:
char szText[] = "Hello World";

int GetText(char* szBuff, int* nBuffSize)
{
      int nTextLength = strlen(szText);
   if(*nBuffSize < nTextLength)
     {
              *nBuffSize = nTextLength;
           return -1;
  } else
 {
              memset(szBuff,0,*nBuffSize);
                strcpy(szBuff,szText);
              return nTextLength;
 }
}    


can you please show me how to convert this function to a dll procedure in Fasm

PS: szText variable can also be defined as local variable of GetText()

Thanks.
Post 29 Dec 2012, 19:05
View user's profile Send private message Reply with quote
HaHaAnonymous



Joined: 02 Dec 2012
Posts: 1178
Location: Unknown
HaHaAnonymous 29 Dec 2012, 20:55
[ Post removed by author. ]


Last edited by HaHaAnonymous on 28 Feb 2015, 22:08; edited 1 time in total
Post 29 Dec 2012, 20:55
View user's profile Send private message Reply with quote
typedef



Joined: 25 Jul 2010
Posts: 2909
Location: 0x77760000
typedef 30 Dec 2012, 02:21
@op Untested. Find any bugs and learn from it.


If calling from C/C++ define the function prototype first as __stdcall.

Code:
HMODULE hLib =LoadLibrary("fasm_code.dll");
typedef int (__stdcall *GetText)(char * pBuff, int * cbSize) = (int (__stdcall*)(char*,int*) ) GetProcAddress(hLib,"GetText");
int length = 12356;
char * myBuffer = (char*)malloc(length);

length = GetText(myBuffer, &length);

    


Code:
format pe gui 4.0 dll

include 'win32a.inc'

entry DllMain

section '.code' code readable executable

proc DllMain
     mov        eax, 1
     ret
endp

;
; __stdcall memset
;
        memset:
            push ebp
            mov  ebp, esp
                cld
                mov     ecx, dword [ebp+16]
                mov     esi, dword [ebp+8]
                mov     eax, dword [ebp+12]
                rep     stosb

            leave
        ret 4 * 3

;
; __stdcall strlen
;
      strlen:; (str)
             push ebp
             mov  ebp, esp
                cld
                mov al,  0    ; Scan for null byte
                mov eax, -1   ; Make the loop infinite until we hit the null byte
                mov edi, dword[ebp+8]
                repne scasb
                mov eax, -2   ; If first byte is null ECX will be -2
                sub eax, ecx
             leave
      ret 4

;
; __stdcall strcpy. Quick and dirty. Not good for production
;
      strcpy:;(str1,str2)
            push ebp
            mov  ebp, esp

               push dword[ebp+12] ; str2
               call strlen
                                 ; check for errors here
               mov  ecx, eax
               cld
               mov  esi, dword[ebp+12]
               mov  edi, dword[ebp+8]
               rep  movsb
            leave
      ret   4 * 2

;
; __stdcall GetText (pBuff, length)
;
        GetText:
             push ebp
             mov  ebp, esp
             push ebx

             mov ebx, theLength
             mov eax, dword[ebp+12]  ; pointer on stack
             cmp ebx, dword[eax]     ; what's on that pointer
             jg  @Z

             push   dword[eax]
             push   0
             push   dword[ebp+8]
             call   memset           ; can also be transformed into a macro

             push   theString
             push   dword[ebp+8]
             call   strcpy
             mov    ebx,  eax
           @Z:
             pop ebx
             leave
        ret  4 * 2

section '.data' data readable writeable

theString   db 'Rush Rush Rush !. Oh no!',0
theLength   = $ - theString

section '.export' export data readable

export 'stringz.dll',\
        GetText,'GetText'

section '.reloc' data fixups discardable
    
Post 30 Dec 2012, 02:21
View user's profile Send private message Reply with quote
Tyler



Joined: 19 Nov 2009
Posts: 1216
Location: NC, USA
Tyler 30 Dec 2012, 04:28
If all you want is to convert C to asm, you can do that (sorta) with GCC, using gcc -S -masm=intel "source.c". It will be in Intel syntax but a little different from Fasm's Intel syntax, so it'll take just a little editing. Also, you'll probably want to use -O3, unless you want your code to be 1000 lines for absolutely no reason.
Post 30 Dec 2012, 04:28
View user's profile Send private message Reply with quote
Xerkan



Joined: 22 Dec 2012
Posts: 2
Xerkan 31 Dec 2012, 12:27
Hi
sorry for late reply

@HaHaAnonymous
yes we usually use the CRT functions in C Smile


@typedef

thank you very much for the example you showed
i tried it ( with __stdcall) but it crashes at the point where memset
i am a Visual Studio user and usually use .def file to export a function from a dll
which means __cdecl calling convention

i can not modify the host application that loads this DLL and i have to export functions as __cdecl 'ed

@Tyler
yes i want to convert C code to Assembly that i can compile with Fasm
actually, my first attempt was the modifying a Assembly output of this function (and others) generated by Visual Studio
but i could not get it to work as well

this is the exact Asm output of visual studio which works well when compiled with Visual Studio

Code:
PUBLIC   ?GetText@@YAHPADPAH@Z           ; GetText
; Function compile flags: /Ogty
;   COMDAT ?GetText@@YAHPADPAH@Z
_TEXT   SEGMENT
_szBuff$ = 8                                         ; size = 4
_nBuffSize$ = 12                                  ; size = 4
?GetText@@YAHPADPAH@Z PROC NEAR           ; GetText, COMDAT
   push    esi
 push    OFFSET FLAT:?szText@@3PADA  ; szText
    call    DWORD PTR __imp__lstrlenA@4
 mov     esi, eax
    mov     eax, DWORD PTR _nBuffSize$[esp]
     mov     ecx, DWORD PTR [eax]
        cmp     ecx, esi
    
    jge     SHORT $L180702

  mov     DWORD PTR [eax], esi
        or      eax, -1
     pop     esi
 ret     0
   
$L180702:

       mov     edx, DWORD PTR _szBuff$[esp]
        push    ebx
 mov     ebx, ecx
    push    edi
 shr     ecx, 2
      xor     eax, eax
    mov     edi, edx
    rep stosd
   mov     ecx, ebx

        push    OFFSET FLAT:?szText@@3PADA  ; szText
    and     ecx, 3
      push    edx
 rep stosb
   call    DWORD PTR __imp__lstrcpyA@8
 pop     edi
 pop     ebx

     mov     eax, esi
    pop     esi


 ret     0
?GetText@@YAHPADPAH@Z ENDP                 ; GetText
_TEXT      ENDS    


note: i forwarded __imp__lstrcpyA and __imp__lstrlenA@4 to msvcrt.dll with import on my tests
and did modifications acorrding the Fasm's error descriptions

can you guys help me to convert this Masm code to Fasm

Thanks for your help
Post 31 Dec 2012, 12:27
View user's profile Send private message Reply with quote
uart777



Joined: 17 Jan 2012
Posts: 369
uart777 06 Jan 2013, 16:39
Useful memory routines:

Code:
;;;;;;;;;;;;;;;; MEMORY COPY, SET ;;;;;;;;;;;;;;;;

function memory.copy, a, b, n
push esi edi
let edi=[a],\
 esi=[b], ecx=[n]
test edi, esi      ; address=0?
jz .e
cmp ecx, 4         ; if n<4
jb @f
push ecx
shr ecx, 2         ; n/4
rep movsd          ; copy dwords
pop ecx
and ecx, 3         ; modulo 4
jz .e              ; remainder?
@@:
rep movsb          ; copy bytes
.e:
pop edi esi
endf

function memory.set, p, v, n
push edi
let edi=[p],\
 ecx=[n]
test edi, edi      ; address=0?
jz .e
cmp ecx, 4         ; n<4?
jb @f
push ecx
shr ecx, 2
rep stosd          ; copy dwords
pop ecx
and ecx, 3         ; modulo 4
jz .e              ; remainder?
@@:
rep stosb          ; copy bytes
.e:
pop edi
endf

;;;;;;;;;;;;;;;; GET/SET/ZERO BIT ;;;;;;;;;;;;;;;;

; 76543210. warning: eax/ecx/edx cannot be used
; as parameters. 'v' should be m, 'i' can be mi

macro get.bit v, i {  ; (v>>i)&1
let eax=v, ecx=i, eax>>cl, eax&1
}

macro set.bit v, i {  ; v|=(1<<i)
let eax=1, ecx=i, eax<<cl, v|eax
}

macro zero.bit v, i { ; v&=~(1<<i)
let eax=1, ecx=i, eax<<cl
not eax
and v, eax
}

; 1111.0000

macro get.nibble v, i { ; (v>>(i*4))&1111b
let eax=v, ecx=i, ecx<<2, eax>>cl, eax&1111b
}

macro set.nibble v, i, n { ; v|=(n<<(i*4))
let eax=v, ecx=i, edx=n, ecx<<2, edx<<cl,\
eax|edx, v=eax
}

; 33.22.11.00

macro get.couple v, i { ; (v>>(i*2))&11b
let eax=v, ecx=i, ecx<<1, eax>>cl, eax&11b
}

macro set.couple v, i, n { ; v|=(n<<(i*2))
let eax=v, ecx=i, edx=n, ecx<<1, edx<<cl,\
eax|edx, v=eax
}

; enable/disable flag

macro enable.f v, n { let eax=n, v|eax }

macro disable.f v, n {
let eax=n
not eax
and v, eax
}

macro toggle n { xor n, 1 } ; invert 1/0

; create AA.BBB.CCCb/AA.BB.CC.DDb BIT structures

function triplet, a, b, c
let eax=[a], eax<<6,\
ecx=[b], ecx<<3, eax|ecx, eax|[c]
endf

function quadruplet, a, b, c, d
let eax=[a], eax<<6, ecx=[b], ecx<<4,\
edx=[c], edx<<2, eax|ecx, eax|edx, eax|[d]
endf

; expand byte AAh to AA.AA.AA.AAh

function convert.8.32, b
push ebx
let eax=[b],\
ecx=eax, edx=eax, ebx=eax,\
ecx<<8, edx<<16, ebx<<24,\
eax|ecx, eax|edx, eax|ebx
pop ebx
endf

;;;;;;;;;;;;;;;;;; POWERS OF 2 ;;;;;;;;;;;;;;;;;;;

; an unsigned number is a power of 2 if only
; 1 BIT is set: if !(n&n-1). subtracting 1
; inverts all BITs. if n=10000000b (80h/128),
; n&01111111b=0

; to find out which power of 2, search n
; for 1st 0 BIT from right to left

; is n power of 2? example: power.2 128
; returns 7

function power.2, n
locals i
let eax=[n]
.if eax<2
  jmp .r0
.end
let ecx=eax, ecx-1, eax&ecx
.if eax
  jmp .r0 ; not power of 2
.end

; which power of 2?
; n--
; loop i=1, n&1<<i, i++

let [n]--, [i]=1
@@:
let eax=1, ecx=[i],\
eax<<cl, [i]++
test [n], eax
jnz @b
let eax=[i], eax--
jmp @f
.r0: let eax=0
@@:
endf

;;;;;;;;;;;;;;;;;;;;; ALIGN ;;;;;;;;;;;;;;;;;;;;;;

; versatile align n/umber by power of 2

; return n aligned to p in eax. in ecx,
; return the quantity to add to make n
; divisible by p. algorithm:

; n+(((p-1)-(n+p-1))&(p-1))

function align.n, n, p
let ecx=[p], ecx-1, edx=[n], edx+ecx, eax=ecx,\
eax-edx, eax&ecx, ecx=eax, edx=[n], eax+edx
endf    


Ultimate HL features: http://board.flatassembler.net/topic.php?t=14768
Post 06 Jan 2013, 16:39
View user's profile Send private message Reply with quote
nmake



Joined: 13 Sep 2012
Posts: 192
nmake 06 Mar 2013, 13:59
uart777, I am being friendly, but I recall you accused someone on the forum for being a HLL programmer and a lover of windows 8, and that he was not a real asm programmer. But now I see you embrace your own type of HLL implementation in assembly. Do you like HLL or not? Smile

If people wanted to use HLL, would they come to an assembly forum..


1. People ran away from assembly, because they needed HLL.

2. Then people came back to assembly, just to re-invent HLL.

Very Happy
Post 06 Mar 2013, 13:59
View user's profile Send private message Reply with quote
uart777



Joined: 17 Jan 2012
Posts: 369
uart777 08 Apr 2013, 14:15
Quote:
Do you like HLL or not?
Z77 is a low-level language, a compact symbol-based version of machine code. I refer to it as HL because most programmers here only understand things in black/white, they do not understand the precise differences between LL/HL code and that is a variable percentage. HLLs can be improved dramatically. My "language":
Code:
!text.n $t
byte *p=t
while *t, t++, then return t-p
end

!text.copy $a, $b
while *b, *a++=*b++, then *a=0
end

!text.attach $a, $b
a+=text.n(a), text.copy a, b
end

!text.equal $a, $b
if text.case, while *a=*b and *a|*b, a++, b++
else, while IT[*a]=IT[*b] and *a|*b, a++, b++
return (*a|*b)
end

!text.compare $a, $b
while *a=*b and *a|*b, a++, b++, then return *a-*b
end

!text.find $t, c
while *t, t++, if *t=c, return t
return 0
end    
Post 08 Apr 2013, 14:15
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< 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-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.