Table of Contents
 


Summary

This IDE was developed as an alternative to FASMW tool, which is supplied in the FASM package. In addition to syntax highlighting this IDE also provides very good navigational capabilities and auto-completion, which are missing from FASMW. These features are the most needed for development of a large project.

The following features are provided by this IDE:

  • Convenient project management
  • Easy access to any source element
  • Syntax highlighting themes
  • Automated source code reuse
  • Freezing of the project workspace
  • Auto-completion for most of source elements

The following screenshot gives overall view of IDE:

 


Directory Structure

I will explain the contents of the package:

  • Help folder contains this HTML document and its images.
  • Library folder contains source code, which can be included into different projects. The concept of code reuse is described later in this document.
  • Projects folder contains all projects as sub-folders.
  • Themes folder contains all color theme files, which can be loaded by IDE.
  • Mfc-Fasm-Edit.Cfg file is the configuration file loaded by IDE at startup. It has such settings as path to FASM directories, path to debugger, the name of the color theme to use and other options.
  • Mfc-Fasm-Edit.exe file is the IDE executable file. Once the package is unzipped you can create a shortcut to this file on your desktop.
  • Reserved.txt file contains all reserved identifiers for Assembly language. It also has some FASM macro names (like invoke). This file is used by a syntax coloring engine. Whatever needs to be colored as a reserved keyword must be included in that file. If you editing this file then follow these rules: a line must begin and end with a comma; there must be no blanks between keywords - only commas. IDE provides a dialog box for editing the file, but you still have to follow these rules.
  • WinApi.txt file contains prototypes of Windows API as they present in Windows header files. IDE uses it to display information tooltips about API. This file can be manually edited to add more API prototypes, however, one rule must be observed: prototype takes only one line in that file. If prototype has a lot of parameters then IDE will create a multiple line tooltip for it.



Project Management

The concept of a project is simple. First of all, the project name is the same as a name of a directory where all project files are located. Also, the name of a root ASM file is the same as project name. Following image shows some details when new project named A1 is created by IDE:

To create/open a project IDE has a dialog invoked from a File popup menu:

To create a new project:

  • Fill the name of new project into an edit box. If you enter the existing project name or invalid character for directory name then OK gets disabled and the message is displayed below the edit box.
     
  • Click OK
     
  • You also can create a new project based on existing project. As an example, you can see in the image - I have Win32Template project set up, so every time I start a new Win32 project I branch it off Win32Template. Simply select the base project in the list and then click OK. All files from base project will be copied into new directory. Some of old files gets deleted and root ASM file is renamed to accept the new project name.

To load an existing project simply select project from a list and click OK. Or double click the project item in the list. The root file of the project is loaded and parsed with all include files. It fills the identifier tables in IDE memory. These tables are used for auto-completion and navigation. Sometimes project has frozen information associated with it. In this case all source files which were opened during closing of IDE (or freezing) will be restored with their scrolling/caret positions, so the IDE loads all information as it were before the project got frozen. See more details about the project freezing later in this document.

Few important points about the contents of a root ASM file:

  • Keep this file small. Put all your code into other (included) files or modules. This will improve the parsing times, because the parsing of a root file with all included files takes most time.
     
  • Put all your global variables into Globals.Inc file.
     
  • There are two lines present in the root file with keys: {INSMODDEF} and {INSMODIMPL}. Do not remove these tag lines. They are needed for IDE to properly include locally created modules and modules from the Library.

 


What is a Module?

The module, in my opinion, is a software building block, which encapsulates some behaviour in such a way that it can be reused in other applications. This reuse can be implemented in two ways:

  • Binary level of reuse.
    Modules are reused in their binary form: OBJ, LIB, DLL.
     
  • Source code level of reuse.
    Modules are represented as a source code.
    IDE uses this way of reusing code.

When you creating a module in IDE (let us name it TString), the IDE will generate two files for you: TString.Inc and TString.Asm. Optionally, you can select what files would be generated. Next, IDE will automatically include these files at their places in a root file. These places are tagged with {INSMODDEF} and {INSMODIMPL} keys.

INC file contains the structure(s), constants and macros to represent an object described by the module, in this case a TString object. ASM file contains code - the set of functions to manipulate the object data structure and behaviour.

IDE has an ability to generate a function body inside ASM file (Ctrl+P). During that process IDE will use the module name to generate a prefix for the function name. This is done to avoid a duplication of names belonging to different modules.

For example: imagine that you have objects TCircle and TRectangle. They both will have method Show. With module prefix these methods will have different (and readable) names: TCircle_Show and TRectangle_Show. It is a great start for Object-Oriented coding!

 


Concept of a Library

The code reuse is a basis for Rapid Application Development. If you have a lot of reusable objects (or modules) in the Library then your next application can be built more quickly. IDE provides this functionality with Library menu:



There are following items in the menu:

  • Add Active Module - this command will copy ASM and INC files of the module you are currently editing into the Library folder. If module already exists in the Library then you will be asked to overwrite it.
     
  • Include Module - this command will show the list of Library modules and you can select any modules you need in your new project and when you click Add Modules the include statements will be generated by IDE to refer to selected modules.
     



  • Knowing the directory structure, IDE can easily generate the relative path for any included files from the Library:



    When looking at the list of includes you can easily see which modules are coming from the Library and which are part of this project in its directory.

This process has a simple implementation. There is no checking if module being inserted is already included, so you may include few things twice or if you including something big - there will be no check for its dependencies. They will not be included automatically. In any case, because FASM is so fast to assemble the root file - you will see the error messages, whatever is missing or duplicated and easily fix the issue. You may include dependencies into bigger modules, but I suggest against that - it will cause problems if two large modules use the same dependencies. New IDE I am designing will have the module dependency solved. I imagine, that this issue of dependency may be solved with some smart macros (which FASM is so famous for!), like with used macro element.

In conclusion, a few points about designing a good module. The good module is the one which will not introduce any building errors when included into any project, like duplicate/missing identifiers. The following few design principles may prove useful:

  • Avoid using global variables in modules. If such module is included into a project, where this variable is not defined - this will cause assembling error. I realize, however, that access to a global variable is faster than to some handle, created by the module. If you prefer globals - simply fix assembling error by adding that global variable into the project (into Globals.Inc file).
     
  • If some constants are defined in the INC file for the module - use prefixes to make sure that no duplicates of these constants may exist in other modules. Same can be said for macros.

    For example: you are developing the module, which provides custom memory management and you need a macro to find next heap block in chain. A simple name for the macro would be GetNext. However, there is a chance that some other module (TLinkList anyone?) can expose the same macro name, because it is too common. It is better to prefix the name with the module name, like HeapGetNext.
     
  • Each function within module should be enclosed in if used/end if construct:



    This will provide smaller executable file if not all module methods are used.
     
  • Usually, the module has an instance structure with some members. Always align the size of that structure on a DWORD boundary. Misaligned object will cause hard to debug problems if allocated on stack as local variable. There are solutions for this, like a simple macro below.



Main Menu Commands

In this section we will examine all menu commands from main menu bar in IDE. I will skip only commands which will be explained in the toolbar section.

File menu:

  • Open Project - this command opens a dialog (see Project Management) with a list of all sub-folders in Projects folder. To load a project simply double click the list item or select it and click OK.
     
  • New Project - same dialog opens, but you can select a project template or create completely new project. In this case IDE will generate a Win32 startup code. I have created a few templates to be included into IDE package.
     
  • New Module - opens a dialog where you can select which files are generated and included into root ASM file:


     
  • Save - see Toolbar Commands
  • Save All - checks each open source file for modifications. If modifications are present then file is saved.
  • Close - see Toolbar Commands
  • Freeze Project and Exit - see Toolbar Commands
  • Exit - closes IDE. If Auto-Save option is not set then modified files will ask for saving, otherwise all modifications are saved automatically.

Edit menu:



All of these commands are on the toolbar and I think they are all too common in source code editors.

View menu:

Tools menu:

  • FASM Include Directory - it opens the following dialog:



    First select the drive letter, then keep double clicking in the list of sub-directories until you find the location of FASM INCLUDE folder. It works like Norton Commander. IDE uses this path for several purposes, like the location of FASM.EXE file and the same path used for parsing FASM include files.
     
  • Source Code Font - see Toolbar Commands
  • Select Debugger - it opens a standard File Open dialog and you need to locate and select the debugger which IDE will launch when Debug command is invoked. Debugger opens on separate thread, so you can switch back to IDE while debugger is stopped at some point in code.

    NOTE: Debugger is set for IDE, not for a project. If you switching between DOS and Windows type of projects you need to select a proper debugger each time you switch. The IDE for OO Assembler will have this properly implemented (I learned a lesson).
     
  • Toggle Color Syntax - it is a remnant of debugging the syntax colored engine. I decided not to remove it. It is fun to use! If you press F6 repeatedly while in source code editor - you will see how the color changes from plain green to the selected theme. If no text is getting disappeared between switches, then engine is properly parsing and coloring the text.
     
  • Adjust Colors - see Toolbar Commands
  • Save Current Theme As - the following dialog opens:



    This allows for saving the current theme under a different name and then by adjusting colors you can create completely new color theme to use. I have created a few themes to be included into IDE package.
     
  • Load - same dialog opens and allows to select and load any existing color theme as a current theme. When Apply Theme at Run-Time checkbox is checked you will see the effect of the theme at run-time, without leaving the dialog.
     
  • Options - the following dialog opens:



    • Auto-Save - each time the source code needs saving - IDE will save the file without asking. I suggest keeping this ON always. In some cases (Auto-Complete, Find In Files, etc.) IDE will need to save all sources before the operation and then it gets annoying if it keeps asking.
    • Cursor Width - cursor is always vertical and can be 1 or 2 pixels in width.
    • Line Spacing - additional pixels between lines of source code.
    • Number of lines in code tooltip - the amount of code you can view in a tooltip.
    • Tooltip duration - how many seconds tooltip is displayed without user interaction.
    • Tabs - first two tab stops in editor. Tabs are expanded as blanks. This last option is kind of fresh. When code is generated by IDE - it may not follow this option.
    • FASM Command Line Flags - you can specify some additional assembling parameters, like the number of passes or amout of memory for FASM

Library menu - see Concept of a Library section.

Help menu:

  • User Manual - opens this document in a default Web browser.
  • About - opens a standard About box with my contact information. If you would like to submit a bug report then prefix the e-mail subject with [BUG] token. If you would like to propose an improvement to IDE, then prefix is [REQ].

 


Local Editor Menu

When you click right mouse button in code editor the cursor is moved to a point of a click and following popup menu is displayed:

Some of these menu items are located on the toolbar, so they will be explained in toolbar section. The rest of commands is described here:

  • Go to definition - navigates to definition of the source element under caret. If the source element is the file name inside include statement, then this file is loaded into editor. Some files from FASM package may not be loaded, but all project and Library files will be loaded by this command.
     
  • Go to next ocurence - See Find Text.
  • Cut - standard clipboard operation.
  • Copy - standard clipboard operation.
  • Paste - standard clipboard operation.
  • Delete - standard clipboard operation.
  • Paste Label - Same as New Label From Clipboard.
  • Copy As Locals Construct - Selected text is copied into editor internal memory (not a Clipboard).
  • Insert Locals Construct - Text from internal memory is pasted at caret location. Then period character inserted, which will cause Auto-Complete to list members of the construct. I used this heavily for quickly typing the local variables. For example: if you select and copy ebp+loc22, then Ctrl+A will cause locals (from loc22) to be listed in Auto-Complete window.
  • View Source Elements - opens following dialog:



    This presents a view into the most of the contents of parser database. By clicking buttons at the top you can fill the list with associated items and navigate to any item by double clicking it. The dialog closes after this and that is unfortunate. Maybe, I should leave it open for futher navigations. However, Go to definition and tooltips provide a better way to navigate than this dialog. On the other hand, you can open the files from FASM package only from here.
     
  • Highlight Occurences - interesting feature, which was developed following the idea of one WASM.RU forum member. He mentioned, that it would be nice to see the usage of a register/variable inside the function. Just put the caret on any token and select this command. All such tokens (case sensitive, words only) in a file will be highlighted with a selection color. The effect disappears once you click somewhere in the source. Use mouse wheel to scroll the view.


     
  • Find In All Modules - see Toolbar Commands.
  • Build Project - see Toolbar Commands.
  • Debug Project - see Toolbar Commands.
  • Toggle Bookmark - toggles bookmark state for a cursor line.
  • Seek Next Bookmark - navigates to next bookmarked line.
  • Seek Previous Bookmark - navigates to previous bookmarked line.
  • Delete All Bookmarks - cleans the bookmark collection for all project modules.



Toolbar Commands



Generate Code Fragments - opens a menu to insert some predefined code at caret location.



Same menu opens if you press Ctrl+Shift combination while editing text. Personally, I found myself not using this command as much as I anticipated. If I need a macro or a structure - I can type it in the same interval as using this menu. And if I need a procedure - a simple Ctrl+P will do it. However, I can see how a developer can forget the exact identifier, like PIXELFORMATDESCRIPTOR. On the other hand, when you type PIX and press Ctrl+Blank - the Auto-Completion engine will offer the list of possible completions.

Most of these menu items are self-explanatory - simply try these commands and see what is typed in editor. I will say a little more about New Label From Clipboard. This command will check the text in Clipboard and if the text looks like an identifier (has only alpha-numerical characters and does not begin with a digit), then IDE will insert following line at caret location:

.[clipboard_contents]:

It is a simple way to generate local labels in a function. The same command is included into Local Editor Menu.



All Project Modules - opens a menu with all modules (INC and ASM files included) from the project, excluding the files from FASM directory and root ASM file:



Selecting the module from the list will load it into editor or navigate to the module if it is already loaded. If the number of modules makes this menu larger than you would like, then to load modules simply switch to root ASM file and use Go to definition command from Local Editor Menu.



All Project Elements - see Source Elements Dialog.



All Functions in Module - this opens a menu with a list of all procedures in the active source file. Local labels (starting with a period) are not listed:



Select the menu item to navigate to a procedure. I am working on improving the navigation for a large number of procedures/labels in a source file.



Cut, Copy, Paste, Delete - standard Clipboard operations.



Save Active Module - saves active source file. The file is parsed at the moment of saving, so if you add any new elements, then saving the file will make Auto-Completion and navigation work for new elements.



Close Active Module - the active source is closed completely. If Auto-Save is ON then file saved/parsed automatically, otherwise you ask to confirm saving if any modifications detected.



Comment Selected Text - each line of selected text checked for a first character being a semicolon. If semicolon is not present, then it is inserted as first character.



Uncomment Selected Text - each line of selected text checked for a first character being a semicolon. If semicolon is present, then it is removed. Only one semicolon is removed. It will not remove multiple semicolons if they are present.



Undo - the modifications will be rolled back one step at a time. There is a little inconsistency, however. For example, you removed a block of 10 lines. This operation is stored in undo buffer as 10 steps of deleting one line. Same with deleting a token - it is stored as removing one character at a time. I will try to improve that, however, I found myself almost never using Undo to restore the whole lot of code! Not sure if it is worth the effort.



Find in All Project Modules - this command will take the token under caret and if such token is present, then it will perform a search of all project modules for such token. The FASM files (from INCLUDE folder) are excluded from search. The following dialog opens when scan is over (searching for hInstance):



This dialog is modal. However, double clicking the list item will navigate to the token occurence without closing the dialog. Also, you can bookmark some of the occurences or all of them. I find this feature very useful in a large code base, when I need to remember where identifiers are used or declared. The dialog is resizable and its location on screen is saved across IDE sessions.



Build Project - first, Save All command is performed. Then root file is assembled by FASM. It is done on the same thread for now, because FASM is so fast! Once the project is built without errors - the following dialog appears:



Dialog will be closed by timer (if no errors were found) after 1.5 seconds or you can close it with close button before the time expires.

If FASM encountered an error - it will be shown in the same dialog:



Double click on the file name with line number and IDE will open the associated source and will select the error line.



Debug Project - the program (EXE or COM) opens in associated debugger. This process runs on the separate thread.



Explore Project Directory - the project directory opens in a standard Windows File Explorer.



Run Target Executable - the project executable file (EXE or COM) will be launched without a debugger present. Just a quick way to check if code is working.



Toggle Bookmark on Current Line - the line with caret will become bookmarked. If line already bookmarked - this bookmark will be cleared.



Seek Previous Bookmark - navigate to a previous bookmark.



Seek Next Bookmark - navigate to a next bookmark.



Remove All Bookmarks in All Files - all bookmarks are cleared from all files.



Adjust Source Code Font - the following dialog appears:



It allows to select a fixed width font for source editor. I have noticed a strange thing, however. WinXP has a lot of nice looking fonts, but most of them have the backslash character replaced with yen character. At first I thought it was a character set problem, but I tried a few charsets with no success. So, watch out for it - this is why the path is included into text sample.



Adjust Source Code Colors - the following dialog appears:



Source elements are listed in the dialog. Also the tooltip sample is shown at the bottom of the dialog. When element in list is double clicked - the standard Windows Color Selector opens. There is a real-time feedback between the Color Selector and theme elements, so as you change color - you will see how the source is looking without leaving Color Selector. Move the slider and look at the source code!



Freeze Project and Exit IDE - IDE stores the names of all opened documents, their scrolling positions and caret row/column coordinates. Also, the active source index is stored too. All that information is saved into project directory. After this - IDE is closed. When same project is re-opened and frozen data file is present - all modules are loaded back and all views scrolled back to their remembered positions. Same for caret positions in each module. Then module which was frozen active is activated. It feels like you never left the IDE!

Not all possible information is stored, however. If you selected anything - the selection anchors will be lost.

 


Source Code Editor

IDE has a very simple code editor. Only fixed spaced fonts are used. No tabs. The usual navigation keys are accepted. Auto-indent is always present. No horizontal scrolling.

HOME key moves the caret to the first non-blank character on the line. If caret is already there, then HOME key moves it to column 1.

Ctrl+Right, Ctrl+Left will navigate between tokens faster than simply using Left and Right keys.

Selection can be made with mouse and with Shift key applied to direction keys. Selection can be of two types:

  • Token selection - any part of a single line is selected.
  • Block selection - one or few full lines are selected. This type of selection always includes new line characters, even if a single line was selected. Block selection will allow full line selection only.

You can select an identifier by double clicking on it or by a single click, but holding down Ctrl key. Also, you can copy a single line into Clipboard without doing anything - just press Ctrl+C key without any visible selection present. To cancel selection simply click somewhere with mouse or press Esc key.

To select the large block (spanning more than one page) - use keyboard, because mouse selection will not auto-scroll the view.

To delete a line (without selection) use Ctrl+Y combination. To insert empty line put a cursor at the end of line and press ENTER key. Using Ctrl+Backspace key when caret is at column 1 will splice lines back together (opposite of ENTER key when caret is in the middle of the line).

Use mouse wheel to scroll the view. View scrolls by 3-line intervals. With Ctrl key pressed - it scrolls by pages.

Use Ctrl+F to search text within active source file:



The initial text in the dialog is a token under caret. Use Ctrl+F3 to search for a token under caret without seeing the dialog. In this case both Case Sensitive and Words Only options will be set to TRUE. Use F3 to search the next occurence of a symbol. When search reaches the end of file - the beep will indicate this fact and search restarts from the beginning of the file.

To provide more informative environment editor uses tooltips. The following information provided by tooltips:

  • Caret is on a structure name or structure member - tooltip shows the entire structure in both cases:



  • Caret is on a global variable - tooltip shows the declaration:



  • Caret is on a macro name - tooltip shows the macro body:



  • Caret is on a constant name - tooltip shows the defined value:



  • Caret is on a procedure/label name - tooltip will show the code at that location (even from different file). The number of lines displayed by tooltip is defined in Options Dialog:



    When dealing with local labels the procedure scope will be respected. Only labels local to a procedure where caret is now located will be displayed.

    HINT: Put your comments for label/procedure AFTER the label itself. It works very nice, when you can see the parameters description in a tooltip. Saves a lot of time when writing code. Same is good for macros - put comments inside and you will see them in tooltips.

  • Caret is on an imported name - the C-language prototype will be displayed:



    The prototypes must be present in WinApi.txt file. See Directory Structure for more details.

Auto-completion engine has two modes:

  • List possible structure members - when you press a period key, the engine will detect if a token before the period is associated with a structure. If such association is found, then all members of that structure will be listed in a small resizable window. The window does not have a Close button, but you can close it by right clicking the list or pressing the Esc key. If you select anything for auto-completion - simply double click that item or press ENTER.



  • List possible completions for a prefix - when you press Ctrl+Blank combination the engine will again detect if any token was present before the caret. If so, then engine will list all parser elements which begin with the prefix at caret:



I want to point out a small problem with Auto-Completion engine. When IDE was done and I started testing it and writing this document, I have noticed that IDE will not complete the structure members for a variable which is itself a structure member. Let me explain with a few screenshots:







I want to load into EAX a member of rcPaint. IDE did not list anything in this case. After investigation - I realized that parser needs to be redesigned to a great extent. That was out of the question, so I found a simpler solution. I adjusted the parser to store a type information for all structure members. This allows parser to "see" that rcPaint is of type RECT. Now IDE properly lists members in such situation.

However, let us look at the following case:



Two different structures have the same named members, but these members are of different types! Whose members to list in this case?

The first thing which comes to mind is that such design of structures is improper, not maintainable. The members must be properly named (POINT instance can't be named rcFrame). Also, Hungarian Notation is nice to use in this case. In this complex case IDE will list all members of all structures involved in such ambiguity:

Auto-Completion engine also "knows" about structures declared using virtual construct. It can be used as an alternative to native FASM implementation of local variables. It is demonstrated by following screenshot:



Before the function implementation the structure is declared for local variables. It should be labelled as locindex, where index is any decimal number.
HINT: use menu item Tools/Find Next Local Index.

In modules, shared between applications, you can use the name which will not collide with other names.

I use the local variables in this way, because FASM native way is to use old stack frames based on BP/EBP registers, also LEAVE instruction is longer to execute than simply adjust the ESP register when entering the procedure and return it back when exiting it. Applied to every procedure this small improvement may be useful if code has thousands of procedures or if it calls procedures with local variables frequently. Besides all that, modern compilers no longer use BP/EBP registers to generate stack frames in production (RELEASEd) code. I simply followed that trend.

Auto-Completion, however, works for old style locals too. As seen on the following screenshot, when prefix dw is typed and user presses Ctrl+Blank - you can see both parameters and locals beginning with that prefix in the same list:

Auto-Completion engine is case sensitive. It means if you type wm_ and press Ctrl+Blank, engine will not find any completions for that prefix. You must type WM_ to get a valid list.