[I am going to preface this article with a brief note, since it is not
covering assembly language per se, but rather a utility that will be of use
to asm coders. The author sums it up well in his original email to me:
"Define is a new type of assembler/disassembler that does not use source
code. The program reads the byte values in memory and checks a library to
find a definition that describes the byte values it reads. The library can
be added to and is used as a permanent macro list to write instuctions,
functions, etc to memory. Most assemblers also use standard 3 character
mnemonics to descibe the instruction set, however, with Define you can
rename the instructions and your own macros to anything and up to 250
characters."
Sounds pretty promising.
_m ]
For the x86 series of processor I have been working on a new type of assembler and have
written a program called Define. The program could be called a sketch of what a future
version might be like. The program is fully workable but suffers from a few limitations,
the first is that it is written in QBASIC which may be a blow to devoted machine coders,
and the second is that it can only comfortably use about three hundred definitions
(Definitions are like a library of machine code macros and I'll discuss them more fully
later) and a third limitation, not to its functionality, is that the program doesn't have
a quick mouse and menu driven interface, but I'm working on it.
I liked the idea of macros and saw the neccessity for using them so that I and others
don't have to "reinvent the wheel" as it has been put, but I wanted a way to see the
machine code instructions and the byte values that made up the macro. This can't be done
through using source code as the finished code is generated at the discretion of the
compilers authors and requires a debugger to verify its content.
To make what was originally intended to be a debugger but without the source code I
decided to make a program that could read memory and interpret the byte values it finds
into their mnemonic equivalents or better (much like a debugger), so that while reading
memory, if the program found the byte value 205 followed by the value 5 it would display
"INT 5". To do this I needed what I termed a 'definiton' which included the byte values
that make up an instruction or small macro and included a description or name for the
function they perform.
Unlike what I had done with a previous assembler I decided to put the definitions in a
separate file rather than include them as data within the main program, this allowed
for the addition or removal of future definitions. I then quickly realised that since
these definitions contained the byte values of an instruction, then they could also be
used to write the bytes into memory. I added functions to save and load programs as
well as functions to manipulate the definition file and the program was underway.
I found while writing the definitions for the instruction set that it would be good
(and necessary) if the program could read an instruction even if one of the bytes is
unknown or variable; I decided to call these bytes undefined bytes, so that if the
program found the number 205 it would display something like "Interrupt call" regardless
of what number followed.
While reading memory I also wanted a way to exclude data areas from being interpreted
into definitions, so I added a new definition type called addresses which contain the
address of the first and last bytes of a data area and a name to describe the data area.
If these are turned on in the program then they are used instead of the normal definitions
when reading that part of memory.
To then take Define closer to being an assembler rather than a debugger I also included
labels that label memory addresses and the destination of jump and branch instructions.
I envision that a future version of Define written in machine code or a similar program
will have a pop up list of definitons and use a point and click method of writing the
code as opposed to the current method of scrolling through them from a different page.
The future version will also need to be able to handle thousands of definitions as
opposed to the few hundred it can use at a time now, in order to accommodate situations
such as the following:
To call the interrupt 21h,9 which prints a string it is necessary to put the function
number 9 in AH and the address of the string in the registers DS:DX and then call the
interrupt,
MOV AH,9
MOV DX,address
INT 21h
however it is also valid to put the number 9 in AH after the address of the string has
been put in DS:DX,
MOV DX,address
MOV AH,9
INT 21h
To make a definition for this interrupt at least two definitions will need to be made
and therefore a larger definition file. This also doesn't account for the situation in
which the number 9 may have been filled three instructions earlier and is assumed to be
correct at the time when the interrupt is called, in this case only the definitions for
the instructions will be seen and not a definition for the interrupt.
One of the best aspects to Define in my book is that the memory can be viewed according
to a persons level of understanding (or will be as the definitions are written,) for
example the program is able to only show definitions of a certain level and no other. I
have chosen to represent the level of a definition by its color, I have used blue (1)
for the lowest level which are the instruction set definitions and then green (2) for
the next level which are the DOS, BIOS, etc definitions and then magenta (3) for the
next level which may be definitions to clear the screen and print the date combined and
so on, so that a person who knows little about machine code may set the maximum definition
color to red (4) and still be able to write a program using Define. The advantage for
those who know machine code is that they need not be restricted to only a high level
definition, by turning the observance of the color off they can press the letter B when
viewing a high level definition and see the lower level definitions that make up the
higher one. By repeatedly pressing B they can view the program as level 1 (blue) or even
as the byte values themselves.
The most radical departure from most assemblers is that when writing a program the program
is composed in memory, the byte values of the definitions are written directly to an
unused or reserved area of memory where they can be further altered directly while
reading memory. This could also be said to be the most dangerous method as it can easily
lead to the accidental writing of other areas of memory, while this is true I have also
found a benefit, if Define is stopped and then restarted the program being written will
still be in memory without having been saved (depending on where in memory the program is
being written.)
The maker of a violin, while demonstrating it, must have said at one time or another "A
good violinist could really show you how to play it", I too like the maker of a violin am
sure there are better definition writers than myself. To become a high level language the
high level definitions need to be written and I ask any person who has a passion for writing
hand written code to send me a definition or two to include in the definition file.
You can download Define from my homepage at
{http://members.net-tech.com.au/alaneb/default.htm}
and there is a step by step guide to using the program in the zip file called manual.doc.
Please send any definitions or reponse to Alan at {
This e-mail address is being protected from spam bots, you need JavaScript enabled to view it
}
|