News:

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

HowTo: simple C program call BinSearch?

Started by l_d_allan, February 20, 2006, 06:27:48 PM

Previous topic - Next topic

l_d_allan

<alert comment="masm32 newbie">

I'm very much a masm32 newbie and a very rusty asm86 developer.

Thanks for providing masm32 .... it looks like it could be a valuable resource. At this point, I am mostly interested in calling masm32 functions from C and C++ programs.

As a "beginner baby step with training wheels on", I was trying to figure out out to invoke the relatively simple BinSearch routine. From there, I wanted to use the Horspool variant of the Boyer-Moore algorithm .... but I figured I would start with BinSearch.

Here is a simple C program just to invoke the routine. I'm stumped how to actually get it to link ok .... I tried command lines such as the following:
cl call_test.c c:\masm32\lib\masm32.lib and
cl call_test.c c:\masm32\m32lib\masm32.lib and

and get "unresolved _BinSearch" errors.

Also, from a C program, what is the appropriate calling convention?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// prototype for BinSearch routine .... fuzzy on calling onvention??
int BinSearch(int startPos, char* strBuf, int strBufLen, char* patternToFind, int patLen);

void BruteForce_C_Search(int startPos, char* strBuf, int strBufLen, char* patternToFind, int patLen)
{
   int i;
   int j = startPos;
   int limit = strBufLen - patLen;

   for (j = startPos; j <= limit; ++j) {
      for (i = 0; (i < patLen) && (patternToFind[i] == strBuf[i + j]); ++i);
      if (i >= patLen) {
         printf("J: %d\n", j);
      }
   }
}

void main(void)
{
   char* test = "abcdefghijklmnopqrstuvwxyz";
//               012345678901234567890123456789
   char* pattern = "ijk";   // should be found at position 8
   int   rc;

   BruteForce_C_Search(0, test, strlen(test), pattern, strlen(pattern));

  rc = BinSearch(0, test, strlen(test), pattern, strlen(pattern));
}


Mark Jones

Hi Allan. I'm a complete C-noobie myself so this may be totally erronious. But whenever I'm linking a separate .obj file to a MASM32 project, the procedures in the added .obj file must be defined so the linker knows how many parameters to pass to the included functions. In MASM32, including external functions is a 2-part process:


    include advapi32.inc     ; registry functions from advapi32.dll
    includelib advapi32.lib

.code
    invoke AbortSystemShutdown,0   ; a procedure in advapi32.dll


Inside the .inc file you'll find a bunch of function prototypes. Here's the one we're concerned with:


; -----------------------------------------------------
; advapi32.inc Copyright © The MASM32 Project 1998-2006
; -----------------------------------------------------

AbortSystemShutdownA PROTO :DWORD
AbortSystemShutdown equ <AbortSystemShutdownA>
...etc


So at assembly time ML.EXE reads our assembly source, sees we INVOKE the function called "AbortSystemShutdown" and finds an equivalent in advapi32.inc, which is passed one DWORD parameter. So in our compiled code the INVOKE syntax is converted to "PUSH 0" then ultimately "JMP NEAR DWORD PTR DS:[<&advapi32._AbortSystemShutdownA>]" or similar. At link time the linker fixes up all these addresses to point correctly at advapi32.dll so the call works properly.

Long story short, if there was no "AbortSystemShutdownA PROTO :DWORD" in advapi32.inc, then we'd get a linker error just like the one you're getting because the linker doesn't know how many parameters to pass to that function. So if you somehow define the function you're trying to import, it should work. Perhaps that involves making a VOID or DEFINE in C, I dunno.

Also be sure to see MASM32.HLP under "Calling Convention" for an important note about calling convention between STDCALL and C.
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

hutch--

ld,

With a library module written with MASM, you need to do 2 things to call it from a C program. You must prototype it using the EXTERN syntax of the particular compiler you are using and you must specify the calling convention so the compiler understands how to balance the stack. Almost all of the masm32 library is STDCALL (__stdcall) with the exception being the szmulticat procedure that takes a variable number of arguments.

Do both and you should have no problems.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

l_d_allan

Thanks for the help (and patience with my newbie questions) ... it seems to be working ok now.

There was a third thing that seemed necessary (in addition to the extern and __stdcall that you mentioned) .... use a compatible code generation flag to multithreaded dll ... I suppose that is the way that masm32.lib is built?

The following makeit.bat worked ok:
@echo off

: ------------------------------
: set the environment variables
: ------------------------------
set MASM32_HOME=X:\DevTools\masm32
set LIB=%MASM32_HOME%\lib\;%LIB%

: -------------------------
cl /MD extern_test.c masm32.lib

if errorlevel 1 goto err_cl
extern_test
goto TheEnd

:err_cl
echo echo Compiler Error
goto TheEnd

:TheEnd

pause


And I changed the extern_test.c code to:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// prototype for external BinSearch routine which is in masm32.lib
// Use command line: cl /MD extern_test.c %MASM32_HOME%\lib\masm32.lib
extern int __stdcall BinSearch(int startPos, char* strBuf, int strBufLen, char* patternToFind, int patLen);

void main(void)
{
   char* test = "abcdefghijklmnopqrstuvwxyz";
//               012345678901234567890123456789
   char* pattern = "ijk";   // should be found at position 8
   int   rc;

   rc = BinSearch(0, test, strlen(test), pattern, strlen(pattern));
   printf("rc: %d\n", rc);
}

hutch--

ld,

The masm32 Project actually builds the masm32 library when you install it so you can see exactly what you get and how its done by having a look at the source code in the m32lib directory and the batch file that builds it.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

l_d_allan

<alert comment="masm32 newbie">

I was trying to figure out how to build a debuggable masm32_dbg.lib so I could use the Microsoft  :naughty:vc6 ide to step-into szRemove and observe how that function works. I'm having a problem with szRemove using a single buffer, and figure I'm doing something wrong.

I looked at makelibs.bat, which referred to include\bldlibs.bat and then m32lib\make.bat. It appears the change would be:
\masm32\bin\ml /c /coff @ml.rsp
to
\masm32\bin\ml /Zi /c /coff @ml.rsp

Is that correct? Besides renaming masm32.lib to masm32_dbg.lib, are there other changes necessary to be able to step-into szRemove with vc6?

It actually seems to work and I can step-into szRemove, but I'm still getting an access violation, and figure it is most likely a setup error on my part.

Here is the modified m32lib\make_dbg.bat

@echo off

del masm32_dbg.lib                  : delete any existing MASM32 debug Library

dir /b *.asm > ml.rsp               : create a response file for ML.EXE
\masm32\bin\ml /Zi /c /coff @ml.rsp
if errorlevel 0 goto okml
del ml.rsp
echo ASSEMBLY ERROR BUILDING LIBRARY MODULES
goto theend

:okml
\masm32\bin\link -lib *.obj /out:masm32.lib
if exist masm32.lib goto oklink

echo LINK ERROR BUILDING LIBRARY
echo The MASM32 Library was not built
goto theend

:oklink
copy masm32.lib \masm32\lib\masm32_dbg.lib
copy masm32.inc \masm32\include\masm32.inc


:theend
if exist masm32_dbg.lib del *.obj

dir \masm32\lib\masm32_dbg.lib
dir \masm32\include\masm32.inc

pause


</alert>