News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

ASM Beginner, Need help understanding Multi-Modular programs

Started by LoveToLrn, January 07, 2014, 01:25:28 PM

Previous topic - Next topic

LoveToLrn

Hi guys, I am having real trouble understanding what I am missing here to get this application to link properly.
My code's only purpose so far is to help me understand how to write an application that "include"'s .inc files that
contain Prototypes for Procedures that exist in other .asm files(I may add more functionality to the code later,
for now I just want to get a linking program that runs). I am using RadASM and its incorporated assemble, link, and build
utilities. As a further question, would someone mind clarifying for me how exactly the linker finds the file that contains the
procedure whose address is to be put into the blank address the assembler puts in when it sees that a procedure identifier
is externally defined, do both .asm files simply need to be in the same directory and have their methods made public?
(I know public for procedures is the default)

Also I am trying to use INVOKE, PROTO, PROC instead of using CALL and EXTERN.

Code:

Ch9_Ex1.asm(My main, or startup module):

.486
.model flat, stdcall
.Stack 4096
option casemap:none
;System Includes---------------------------------------------------
include windows.inc
include user32.inc
include kernel32.inc
include shell32.inc
include comctl32.inc
;------------------------------------------------------------------
;System Libraries--------------------------------------------------
includelib user32.lib
includelib kernel32.lib
includelib shell32.lib
includelib comctl32.lib
;------------------------------------------------------------------
include Ch9_Ex1.inc

.data
string1 BYTE "Test string here!"
string2 BYTE 20 DUP(?)
charCount DWORD 04h
.code
start:
invoke Str_copyN, ADDR string1, ADDR string2, charCount
invoke ExitProcess,eax
END start


Ch9_Ex1.inc:


Str_copyN PROTO,
source:PTR BYTE,
target:PTR BYTE,
numChars:DWORD


Str_copyN.asm(My externally defined procedure):


.486
.model flat, stdcall
option casemap:none
include Ch9_Ex1.inc
.code
Str_copyN PROC USES ecx esi edi,
source:PTR BYTE,
target:PTR BYTE,
numChars:DWORD

mov ecx,numChars         ;Set amount of characters to copy
inc ecx ;Add 1 for null byte
cld ;Clear direction flag
mov esi,source         ;Set up source for string prim. instr.
mov edi,target         ;Set up source for string prim. instr.
rep movsb ;Copy the source to target string

ret
Str_copyN ENDP
END


The problem is that the linker isn't resolving the address of Str_copyN in Ch9_Ex1.asm.
Any help is very appreciated, Thanks everyone!

bsdsource

This is how I typically would do it in my project:

Ch9_Ex1.asm(My main, or startup module):
.486
.model flat, stdcall
.Stack 4096
option casemap:none
;System Includes---------------------------------------------------
include windows.inc
include user32.inc
include kernel32.inc
include shell32.inc
include comctl32.inc
;------------------------------------------------------------------
;System Libraries--------------------------------------------------
includelib user32.lib
includelib kernel32.lib
includelib shell32.lib
includelib comctl32.lib
;------------------------------------------------------------------
include Ch9_Ex1.inc

.data
string1 BYTE "Test string here!"
string2 BYTE 20 DUP(?)
charCount DWORD 04h
.code
start:
invoke Str_copyN, ADDR string1, ADDR string2, charCount
invoke ExitProcess,eax

include Str_copyN.asm
END start


Ch9_Ex1.inc:
Str_copyN PROTO source:PTR BYTE,target:PTR BYTE,numChars:DWORD

Str_copyN.asm
Str_copyN PROC USES ecx esi edi source:PTR BYTE,target:PTR BYTE,numChars:DWORD

mov ecx,numChars         ;Set amount of characters to copy
inc ecx ;Add 1 for null byte
cld ;Clear direction flag
mov esi,source         ;Set up source for string prim. instr.
mov edi,target         ;Set up source for string prim. instr.
rep movsb ;Copy the source to target string

ret
Str_copyN ENDP


Might be a better way. But his approach should work for you. Also notice the comma's I removed from your source code.

dedndave

one way to do it is to
assemble the main source to create an OBJ
assemble the smaller source(s) to create OBJ(s)
then, list all the OBJ files on the LINK command line
that means that a special batch file is needed and you have to modify it every time you add or remove a small module

it can also be done using the MAKE utility

a simple way, though, is to put the smaller modules into a static library
then, in your main source
    INCLUDE     <all the normal INCs>
    INCLUDELIB  <all the normal LIBs>
    INCLUDE     MyLib.inc                       ;define the prototypes and constants associated with your library
    INCLUDELIB  MyLib.lib


the advantage is that you don't need a special batch file
and, you only update MyLib.inc/lib when necessary

LoveToLrn

Thanks for the tips guys!
Dave I was wondering how would I create an object file library to then add my assembled obj's to?
I have tried to create one  in Visual Studio 2012 but it seems to be C++ specific and not for ASM.

dedndave

i'm sure there's a way to do it with visual studio
thing is, as long as you can create the OBJ (C or ASM), you can do it with the linker

http://masm32.com/board/index.php?topic=2743.msg29059#msg29059

examine the batch file to see the command lines that are used

dedndave

to manage the library.....

you can add or remove individual modules

first, let me explain that the library manager is available as part of Link.exe
but, it may be simpler to use Lib.exe
when you run Link.exe and use Lib command switches (/LIB), Link.exe "calls" Lib.exe

C:\Documents and Settings\Dave\Desktop => Lib/?

C:\Documents and Settings\Dave\Desktop => Microsoft (R) Library Manager Version
5.12.8078
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

usage: LIB [options] [files]

   options:

      /CONVERT
      /DEBUGTYPE:CV
      /DEF[:filename]
      /EXPORT:symbol
      /EXTRACT:membername
      /INCLUDE:symbol
      /LIBPATH:dir
      /LIST[:filename]
      /MACHINE:{ALPHA|ARM|IX86|MIPS|MIPS16|MIPSR41XX|PPC|SH3|SH4}
      /NAME:filename
      /NODEFAULTLIB[:library]
      /NOLOGO
      /OUT:filename
      /REMOVE:membername
      /SUBSYSTEM:{NATIVE|WINDOWS|CONSOLE|WINDOWSCE|POSIX}[,#[.##]]
      /VERBOSE


http://msdn.microsoft.com/en-us/library/e17b885t.aspx

if you use no switches, Lib creates a library from the modules on the command line

if you use /OUT:filename.....
if filename is the name of an existing library file, the object modules are added to it
if filename is the name of a library that does not exist, it creates a new one and adds the modules

use /REMOVE to remove modules

jj2007

Quote from: LoveToLrn on January 08, 2014, 12:50:55 AMI have tried to create one in Visual Studio 2012 but it seems to be C++ specific and not for ASM.

Building an assembly library in VS is a serious overkill. Use qEditor or similar...
Here is a very simple example how to use a static library, tested with VC++ 2010 Express (Win32 Console app, nothing special - hit Ctrl F5 to build & run):

#include "stdafx.h"
#pragma comment(lib, "\\Masm32\\lib\\masm32.lib")   // the static library

extern "C" int __stdcall StrLen(char* pString);

int _tmain(int argc, _TCHAR* argv[]) {
   char* MyString="Hello World";
   printf("The string '%s' is %i characters long\n", MyString, StrLen(MyString));
}