News:

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

DIVIDE ET IMPERA

Started by frktons, September 14, 2010, 04:53:36 PM

Previous topic - Next topic

frktons

Somebody in the English speaking countries traslated the Latin saying

Divide et impera

into a similar, but still slightly different:

Divide and conquer.

Now what's the matter of dividing things in order to better manage them?
Here we have an example: big programs, the bigger the more difficult to manage.

I'm not yet at that point with my small ridiculous ASM examples,
but, as time passes, they are becoming bigger nevertheless.

I'm already in the hundreds of instructions. So before reaching the thousands
it'd better start dividing them.  :P

I'd like to ask something about this matter to the more experienced ones, probably
all of you are more experienced ASM programmers than me.

Let's use as an example a recent code, ASCII.ASM, some hundreds lines.
Inside the prog I have more or less a dozen PROCs. If I'd like to expand this prog further,
adding a menu, many more screens, dozens more PROCs, it'll get much bigger
and less manageable.

My question is, what do you usually do to organize your projects?
Do you use static LIBs to include, or DLLs, or you prefer a bounce of
OBJ inside a folder and you link them together with a MAKE file?
Or what else?

Any comments about the method you use, and why, would be much appreciated.

Thanks

Frank

Mind is like a parachute. You know what to do in order to use it :-)

redskull

A properly written MAKE files is your best friend in the world.  Also, become comfortable with condition includes in the preprocessor, and variable scope (EXTERN, etc).

-r
Strange women, lying in ponds, distributing swords, is no basis for a system of government

frktons

Quote from: redskull on September 14, 2010, 05:19:28 PM
A properly written MAKE files is your best friend in the world.  Also, become comfortable with condition includes in the preprocessor, and variable scope (EXTERN, etc).

-r

Do you suggest having a pool of OBJ files in the project folder and using the MAKE file
to link them together? Or the MAKE files selects the souce code to Assemble and Link?

If a routine is used by many programs is it better to have it in a LIB?

The includes have to be all at he beginning of the prog, before the .DATA section, or you
can also choose a different location?
I mean, can I include a PROC in the middle of a source with the proper preprocessor directive?

Sorry for the n00bbyst questions, but I'm still quite ignorant in this field.  :P

Frank

Mind is like a parachute. You know what to do in order to use it :-)

redskull

Generally I prefer object files, but a lot depends on the circumstances.  I only use a static library if I have an actual "library"; a group of generalized functions that can be used across several programs.  If I'm just breaking up an application to make it more managable, i keep the object files around.

You can INCLUDE anything you want, anywhere you want; the assembler just "copy and pastes" the contents of the included file to that spot.  So, if you have a file with just a PROC, you could include that inside the .code segment of another program and it would work fine (assuming you don't do it inside another PROC).  That's bad style, though, and I would keep executable code of the include files.

-r
Strange women, lying in ponds, distributing swords, is no basis for a system of government

frktons

Quote from: redskull on September 14, 2010, 06:58:19 PM
Generally I prefer object files, but a lot depends on the circumstances.  I only use a static library if I have an actual "library"; a group of generalized functions that can be used across several programs.  If I'm just breaking up an application to make it more managable, i keep the object files around.

You can INCLUDE anything you want, anywhere you want; the assembler just "copy and pastes" the contents of the included file to that spot.  So, if you have a file with just a PROC, you could include that inside the .code segment of another program and it would work fine (assuming you don't do it inside another PROC).  That's bad style, though, and I would keep executable code of the include files.

-r

Thanks redskull, this is much more clear for me.

I am not sure I properly grasp one sentence of yours :
I would keep executable code of the include files
what do you mean?
Mind is like a parachute. You know what to do in order to use it :-)

redskull

Include files should contain just assembler directices for definitions, such as EXTERN, PROTO, TEXTEQU, STRUCT, macros, etc, etc.  Keep anything that actually generates code (and obviously machine instructions themselves) in source files/object files.  For example, if two source files both need to use a defined 'foo' STRUCT, then you should have one common .INC file that contains the definition, and each .asm file include it somewhere near the top.  If you plan to use libraries and makefiles, you'll need a seperate include as well.

-r
Strange women, lying in ponds, distributing swords, is no basis for a system of government

frktons

Quote from: redskull on September 14, 2010, 07:24:54 PM
Include files should contain just assembler directices for definitions, such as EXTERN, PROTO, TEXTEQU, STRUCT, macros, etc, etc.  Keep anything that actually generates code (and obviously machine instructions themselves) in source files/object files.  For example, if two source files both need to use a defined 'foo' STRUCT, then you should have one common .INC file that contains the definition, and each .asm file include it somewhere near the top.  If you plan to use libraries and makefiles, you'll need a seperate include as well.

-r


Oh, maybe you were talking about OBJ files when you said
QuoteI would keep executable code of the include files
this was confusing me, I was thinking about EXE files.

OK I got your points. Good suggestions. Thanks again.  :U

Frank
Mind is like a parachute. You know what to do in order to use it :-)

redskull

Quote from: redskull on September 14, 2010, 07:24:54 PM
I would keep executable code of the include files

"I would keep executable code OUT of the include files"

I just can't type  :red

-r
Strange women, lying in ponds, distributing swords, is no basis for a system of government

clive

At the end of the day you have to do what works best for you.

If you can partition the code into individual DLL's with clean, well defined, and stable interfaces, and you can handle situations where the versions might be mismatched (backward/forward compatibility) then EXE+DLL's is a good way to go.

I've managed projects which have one function per file, and have thousands of functions. It can be very hard to find things, and you need tools to realistically navigate the project (Understand C++). If many people are working on the project, it makes sense to keep the files small and specific, so each piece has a clear interface, and can be tested by itself. It is much more difficult for one person to keep a model of the entire project in their head, and different people need to understand their own sub-project and how it might interact with others.

With source code management (SCM, ie CVS, Subversion, Git, etc) you need to be able make a snapshot of the entire project, so that you can recreate an old version/release/branch from scratch by pulling out the entire snapshot. Also you learn to use merge tools (WinMerge, Araxis) to pull functions into and across different branches. They are also useful to understand what changed between code that worked, and code that failed, where bugs were introduced, etc.

Personally I prefer to develop code in a monolithic file, keeping things fairly modular and grouped together. When it becomes practical/realistic to break it into sub modules I will do that, but you'd want to limit the number of files to a few dozen. I'll do this either by putting the code in separate source files, or bring it into the primary code as an include file. Your tolerance level might be different, but editors/compilers/assemblers these days can load/process very large files, historically this was a limiting factor. Given that I use SCM, the fact I have multiple instances of the same file isn't too problematic, provided you don't mix up the internal ordering of the file, it is very easy to use merge tools to pick and chose code changes that need to brought in. The reason to keep the file count low is to ensure there aren't a lot of dependencies within the project, with no external dependencies, and to be able to keep track of it in your head. External dependencies are best handled by using a DLL, to provide a rigid interface. If the interface is more fluid then it makes more sense to pull it into the project, but try to provide/consider some partitioning so that you can pull it out of the project later if the interface becomes more solid, or you can make it common to multiple projects.

Use libraries where you can, the linker should be able to cherry pick the pieces it needs rather than pulling in the whole thing.

With an embedded mindset, I would also try to statically link as much as possible. It will make the file larger, but it's behaviour will be more predictable and it can stand by itself. It is a nightmare to provide technical support when you have no control of the DLL's on the target system. Even when using "standard" DLLs you can get systems that contain a near infinite spectrum of versions, some things you expect to work might not, and it's very hard to test all possible scenarios. That's not to say don't use "standard" DLLs, but rather consider what functions to use, and what systems you expect to run on.

Use MAKE files whenever possible, use a batch file if you only have a few files, but always try to automate the build process so you don't have to remember what compiler/assembler and options to use.

It's also quite important to note in the project documentation and source code, the versions of the toolset being used, and the expected compiler command line and options. This can be very helpful when you come back to something 10 or 20 years later, and you have to remember that the project expected to use the Microsoft "huge" model, or that certain optimization options on C 6.00 resulted in bad code generation in function xyz.
It could be a random act of randomness. Those happen a lot as well.

frktons

Thanks clive,
many points to consider indeed.
I think I'm going to be the only developer, I've already gone past the point
of working with code, and team development in particular.
I'm learning MASM for fun, and I'll code something for my personal use/amusement.
It could become a big project nevertheless.
So probably I'll stick with static LIBs, MAKE files, Project folder, as a starting point.
These seems to be the more appropriate, according to your comments.

If I'll mix C/C++ and MASM code, the tools provided with C/C++ compilers could be
quite useful.

Frank
Mind is like a parachute. You know what to do in order to use it :-)

Gunther

I would like to underline every point of Clive's reply. Very important points.

Just another small note by me. It's mostly a good idea to comment your source code well, especially by writing assembly language applications. That's helpful by the program documentation (a weakness of many coders), by the maintaining, and last but not least, by navigation through the different source, include etc. files.

Gunther
Forgive your enemies, but never forget their names.

frktons

Quote from: Gunther on September 14, 2010, 09:06:18 PM
I would like to underline every point of Clive's reply. Very important points.

Just another small note by me. It's mostly a good idea to comment your source code well, especially by writing assembly language applications. That's helpful by the program documentation (a weakness of many coders), by the maintaining, and last but not least, by navigation through the different source, include etc. files.

Gunther


:U
Mind is like a parachute. You know what to do in order to use it :-)

jj2007

Quote from: clive on September 14, 2010, 08:04:39 PM
Personally I prefer to develop code in a monolithic file

Good to see I am not the only one :bg
As you wrote, speed used to be a limiting factor, but nowadays you can handle 10-20k lines of code without measurable delays, so why split and start bothering with complex setups... the 12k lines of my editor assemble and link in less than 0.6 seconds with JWasm. And it's just cute to type hEdit and see immediately the 75 instances where that handle was used, and be sure there is no other tiny nasty little include file where that handle was misspelled or cleared by accident or whatever.

clive

Yes, speed and size. Didn't quite get that in, although did think about it later.

When it took your 4.77/8 MHz PC 5 minutes to compile something, you would usually want to minimize the amount of stuff it recompiled (small files, make building the ones that changed). You'd go off and have a coffee/tea break while the thing ground along. What took minutes now takes milliseconds. It changes the way you attack problems, and debug things, you adapt, but it does give you a different perspective than someone starting today clicking away on their IDE.
It could be a random act of randomness. Those happen a lot as well.

frktons

Quote from: jj2007 on September 14, 2010, 09:53:33 PM

...Speed used to be a limiting factor, but nowadays you can handle 10-20k lines of code without measurable delays, so why split and start bothering with complex setups... the 12k lines of my editor assemble and link in less than 0.6 seconds with JWasm. And it's just cute to type hEdit and see immediately the 75 instances where that handle was used, and be sure there is no other tiny nasty little include file where that handle was misspelled or cleared by accident or whatever.

If I understand your choice, you prefer to have single source code, with lots of MACROs and a static LIB [MASMBASIC], that is
similar, to some extent, to the guideline I'm going to follow.

Quote from: clive on September 14, 2010, 10:15:52 PM
Yes, speed and size. Didn't quite get that in, although did think about it later.

When it took your 4.77/8 MHz PC 5 minutes to compile something, you would usually want to minimize the amount of stuff it recompiled (small files, make building the ones that changed). You'd go off and have a coffee/tea break while the thing ground along. What took minutes now takes milliseconds. It changes the way you attack problems, and debug things, you adapt, but it does give you a different perspective than someone starting today clicking away on their IDE.

Well these are very good points indeed  :U
Mind is like a parachute. You know what to do in order to use it :-)