I am finally done coding the first version of OASML, short form of
Open-source Assembly Library, which is the library of different routines dealing
with variety of subjects including memory, strings, I/O, keyboard, Files and etc.
OASML 1.0 targets real-mode architecture. The majority of the instruction-set is
compatible with 8086 except for a few SHR and/or SHL cases in which 80186
instruction-set is used.

Below is the list of some important features of OASML 1.0:

1) The library uses 8086 instruction set throughout the code except for
  a few cases of shifts that 80186 instructions are used.

2) Each and every procedure in the library can be used independent from
  the other procedures by simply copying and pasting the code in your own program.

3) None of the units use the DOS trap "INT 21h" except for the
  "DOS" and the "Files" unit.

4) The OASML 1.0 library supports inline parameter calling convention for
  some procedures and function in which the programmer is allowed to include
  the parameter in the code segment and the procedure/function would access
  and skip over it after it is done executing. For example, you can write
  a null-terminated string in your code segment right after the invocation
  of the "WriteInlineStr" procedure. The procedure would then read the string
  and write it to the console window and then skip over the string and moves
  to the next instruction in the code segment.

5) Every single line of the code is commented and given full description.

6) Each and all of the procedures in the library are given separate description,
  the details of the calling convention used, examples and notes.

7) All of the procedures in OASML 1.0 are given an example of usage
  and sometimes even two.

8) The PASCAL calling convention is used throughout the library, pushing
  the parameters from left to right. An exception is made to this convention
  in which procedures in this library do not remove the parameters from
  the stack for convenient.

9) The state of the general purpose registers is saved throughout the code,
  leaving them unmodified after the execution of each of the procedures.
  An exception to this is stated by a few procedures.

10) The AL register is used for 8 bit return values of function.
    The AX register for 16bit functions, DX:AX for 32bit functions and
    DX:CX:BX:AX for 64bit functions.

11) Each procedure in the library has a series of notes written as comments
    which point out the important behavior of that specific procedure.

12)  OASML 1.0 does not use string instructions at all for them being rather
    sluggish compared to simple instructions such as "MOV".

13) OASML 1.0, although a 16bit library, has full support for 32bit values
    including simulated instructions such as "XCHG", "MOV", "INC" and etc.
    I/O routines in the library also support the input and output of
    DWORD values. The Conversion unit can be used to convert DWORD values
    to Hex/Octal/Binary and etc.

14) The policy of OASML 1.0 is toward using null-terminated strings
    throughout the code for convenience.

15) The functionality of the library is extended through the implementation
    of a few macros that simplify the usage of a group of frequently-used
    instructions.

16) Throughout the library, offsets from which parameters are retrieved assume
    the "NEAR" call invocation. If you wish to use "FAR" calls, you could add
    the value "2" to each of the offsets in the stack frame
    created for some procedures.

17) Each procedure features a commented header which gives a full description
    about the purpose of the procedure and also exact details of the parameters
    and their size and description, additional notes on the procedure,
    example(s) and etc.

18) The library fully supports signed and unsigned integral values including
    input, output and conversion.

19) The Memory-Management unit does not include "Malloc" and/or "Free"
    procedures for now. I hope I will be able to implement these procedures
    in the next release.

20) The "String" unit features procedures and functions to work with null-terminated
    strings including the string comparison, copying of strings, finding strings,
    string tokenizer and etc.


You can download OASML 1.0 from my Http://www.ASMTrauma.com. Let me know what you think of OASML.
Posted on 2006-10-09 07:08:29 by XCHG
hi, i am making multilatform 32bit library. i will have first version soon.

to yours, it has few very common (TOO common) critical problems:
1. lacks any error handling
2. lacks any design

without this you cannot make solid library. i spent more time with error handling and testing in extreme cases than with rest of things together
Posted on 2006-10-09 08:56:56 by vid
I believe that I have already averted common pitfalls but i also believe that this is the Assembly programming language and not a HLL; therefore, the programmershould be responsible for handling errors not the library. The library can do its job given the correct input as already stated in the Notes section of OASML but if you are giving it an offset instead of a segment address for example, then it's *your* fault and not the library's. Anyway, it'd be nice if you could tell me specifically which of the procedures in this library do not handle common errors as it should be.

Thanks for your concern.
Posted on 2006-10-10 02:25:25 by XCHG
GetParamBlock - how do you set size of buffer, to prevent overflow? same for GetAppPath, and all string functions.  This was common problems in standard C library for many many years, until they realized they have to allways pass size of buffer to function, too. Other way it's very hard to prevent buffer overflows

Anyway, sorry, i found out you do have error handling there. What you miss is error catching. I believe purpose of library is to ease programmer's job. catching errors for programmer (where it is possible) is very helpful - why not to do it?

by the way, why do you use "dw 10CDh" instead of "int 10h" ?
Posted on 2006-10-10 03:07:37 by vid
The first Note of the procedure says (quote) "The string is recommended to be 255 bytes long, at least." although I seem to have forgotten to mention the same thing for the procedure. And for passing the length of the string to every procedure I think it'd be merely overkill once you are told how many bytes your buffer is recommended to have. Case in point, The "SendMessage" Win32 API can be provided the length of the string to be copied from a window with the WM_GETTEXT message but the "wParam" would *not* indicate the length of the buffer pointed by "lParam", it is simply the amount of bytes you wish to copy from the source window's text. The same story must be with the C libraries, allowing the number of bytes to be copied to the buffer to be specified not the length of the buffer.

Now would it be rational if I wanted to retrieve like only 5 bytes from ARGV while the procedure is clearly saying "GetParamBlock" which returns the *whole* block which could be of a variable length?

Once again, I appreciate your concern.

P.S: I added the same note to the procedure. Thanks to you.
Posted on 2006-10-10 04:39:42 by XCHG
now think about case, when you need to work with data from external source, like file or internet. there is an 30byte array for name, null terminated string. you need to copy this name into your buffer.

it comes natural to everyone using string copy, forgetting about case when string is NOT null terminated. In this case you copy more than 30 bytes, your destination buffer will likely overflow and overwrite other data behind it. this is how most exploits work, and it is caused because programmers got used to working with strings in limited buffers, without passing buffer size.
Posted on 2006-10-10 04:46:13 by vid
XCHG: what you need is MAX_PATH+1, where MAX_PATH is defined as 260. But, surprise surprise, you can have longer file/whatever names than this on NT.

For just about everything that has to do with writing into buffers, you need to pass a destination-buffer-size, except for very low-level "working horse" routines. Anything else is a recipe for disaster. Just look at m32lib's vulnerable command line routines, where the proposed "fix" is to bail out if command line is too long...
Posted on 2006-10-10 05:10:25 by f0dder
i am having argument right not with some OpenBSD strlcpy() developer whether source buffer is needed too.

i say yes, it can help catching even more errors.
Posted on 2006-10-10 10:03:46 by vid
Source buffer length checking isn't nearly as necessary as destination buffer, though. Of course in some extreme situations you can get a pagefault by reading too far, but... well :)
Posted on 2006-10-10 10:14:30 by f0dder
Btw, often it's more time-consuming to wonder whether to implement (and provide) feature#1 or feature#2, than implementing (and providing) them both :) .

For file-paths, it's a must to provide destination buffer size.
But for procs like strcpy, you can provide both versions (one with, and one without known buffer-size).
Posted on 2006-10-10 10:27:43 by Ultrano
i don't agree about providing both. most people are lazy and will use worser one, and after error happens they will blame you for providing it.

also i think that it is also purpose of library to "teach" people write proper code, but this is subjective.
Posted on 2006-10-10 11:33:15 by vid
I really don't know why I had to assume that non null-terminated string were going to be used while the intention obviously here was to work with null-terminated strings as the 14th statement in the details of the library states "The policy of OASML 1.0 is toward using null-terminated strings throughout the code for convenience. ".

If you would like to copy for example 30 bytes from the source to the destination whether or not the source is null-terminated, you could use the in the unit which allows the maximum length to be specified. However, I will implement a set of new procedures and functions to accept the length for the destination and/or the source.
Posted on 2006-10-11 03:51:42 by XCHG
good decision. and now the hard part - how to beheave if dest / source string is not zero terminated inside the buffer ;)
Posted on 2006-10-11 07:40:31 by vid
Well let?s say the accumulator holds the requested maximum length and data register is used to read from source and copy to the destination. The accumulator needs to get DECremented and be checked if it reaches zero. The procedure should exit as soon as AX is zero or as soon as a null byte is detected in the source string. The destination should then get terminated by a null-byte anyway. ummm!
Posted on 2006-10-11 07:49:12 by XCHG
and what if ax=0?

and what about strcat? what about strcat when dest string isn't zero terminated already? zero terminate it or leave it as is?

what about StrInsert? how to beheave if strlen(dest)+strlen(source) > dest_buffer?

there are MANY funny cases, i fortunately already have this part behind me, in my library
Posted on 2006-10-11 07:56:01 by vid
Well the first case is really easy. just a TEST on accumulator. The second is already done in OASML too if you look at the notes where it says "The destination string will be terminated by null by the procedure". Every procedure in OASML which somehow copies some string from somewhere to another string, terminates the string by null.

The third one is just ridiculous because you need not worry about it. You should just go until you find the null-terminator or to the extent indicated by the length parameter.
Posted on 2006-10-11 09:07:14 by XCHG
okay, you will find out ;) :P
Posted on 2006-10-11 10:18:42 by vid
Okay, so I've already started coding the length-dependent string algorithms and I was wondering what kinds of string routines could possibly be of more use to the users than the others so that I will be focusing on those more. A list of procedures or a very short tip will do. Thank you guys.
Posted on 2006-10-15 08:34:35 by XCHG
here is mine:
Attachments:
Posted on 2006-10-15 16:38:26 by vid