Bin2Inc.exe | Snooze | FillListBox | FindL | FindSI | TTFTest | About | Home

Mascotr_harvey

Library Code

Bin2Inc.exe

bin2inc source.bin output.inc [label]

This 32-bit Console application converts any file into Assembly or C source code. Written in standard C, this program quickly interprets any binary data, creating DB lines in the file you specify. We use this utility to help maintain the dictionary in HTMLcat. It is a command line program because it is often part of a multiple-step process that is managed by a batch program.

bin2Inc c:\windows\media\chimes.wav  d:\app\resource\chimes.inc

There may be multiple files in a project using the same root name, such as CHIMES.WAV, CHIMES.C, and so forth, so by default this program creates unique names based on the file name; in the example above, the label is chimes_wav:. You can change the label if you like. In addition, an equate with a value of the length of the data is added to the output file.

With this utility, you can create custom data files, such as image libraries or dictionaries, and store them with pointers to variable-length data in one large file. Or use it to add any binary data to programs. Using off the shelf utilities and this program, you can create look-up tables and data in large applications, that nearly maintains itself.

If you would like to create data files for your applications, source code for this program and instructions for creating data files are available for a fee. See the license and limitations for use in BIN2INC.TXT.

Mascot

Snooze

I don't like screen savers or computers that turn themselves off if you don't press a key every now and then. Occasionally, computers refuse to restore themselves from the sleep state. Monitors have to run for up to a half hour before they can display an accurate image. Most hard drive problems happen when they spin-up. I don't like turning off a computer if I anticipate using it within the next hour. I also don't like CPUs and monitors running at full-blast if they're used intermittently. That's enough negativity.

If I'll be away for quite some time, I turn the computer off. I keep a shortcut to a tiny utility called Snooze handy. When I'll be away from the screen for a couple of minutes, I run it. The program sets the monitor in 40x25 text mode with a black screen, and it puts the CPU in an idle loop. Air at the top of the monitor (a ViewSonic A75S) is normally about 92.5-degrees; when Snooze is running, monitor temperature goes down to 85-degrees. At the same time, exhaust air from the back of the computer goes down by about 2.5-degrees.

There's nothing magical, or even very sophisticated, about Snooze. It's just a little more than 100 lines of Assembly language code.

You can do something similar by placing a shortcut to \Windows\System\Blank Screen.scr on the desktop, and clicking it when you don't want the computer to be at the center of your life. If there's enough interest, I'll make Snooze available for download.

Mascot

FillListBox - Low-overhead Windows

void __stdcall FillListBox(
   HWND,   // Handle of the control
   void *   // Pointer to a string pointer array
);

Anybody can fill a list box; it's right up there with Hello, World in complexity. But can you do it small and quickly, where if it is slow, it's the fault of the operating system, not you? That's the goal of FillListBox(). If there is any unnecessary overhead, it's in the call to the SendMessage() function.

This function shows perhaps the least intuitive way to write Assembly language: for the processor, not the programmer. It is absolutely optimized, with every concession for pipelining, efficient instruction ordering, and fast memory addressing. If you're an Assembly language programmer, the first thing you will notice is that it does not push arguments on the stack before function calls. It has that disturbing habit of testing a register, then not checking the results for some time. There is almost always benefit in unwinding loops, but not always, which is why the loop is unwound just one time (which reduces loop overhead by fifty-percent -- not bad for just a handful of instructions).

FillListBox Source Code

Requiring Microsoft MASM 6.11 or later, this flat-model function can be linked with your C/C++ projects.

; (C)2007 R.E.Harvey, All rights reserved
.386
.MODEL flat, stdcall
OPTION PROLOGUE:NONE, EPILOGUE:NONE
LB_ADDSTRING    EQU 0180h  ; 0401h
LB_RESETCONTENT EQU 0184h  ; 0405h
LB_ERRSPACE     EQU -2t
EXTERNDEF _imp__SendMessageA@16:NEAR32
EXTERNDEF _imp__SendDlgItemMessageA@20:NEAR32

.CODE
FillListBox PROC PUBLIC, ?hWndControl:HWND, ?StringArray:NEAR32 PTR
   sub   esp, 28
   mov   [esp + 16], edi
   mov   [esp + 20], esi
   mov   [esp + 24], ebp
   mov   ebp, [esp + 32]
   mov   esi, [esp + 36]
   mov   edi, DWORD PTR _imp__SendMessageA@16
   mov   [esp], ebp
   mov   DWORD PTR [esp + 4], LB_RESETCONTENT
   mov   DWORD PTR [esp + 8], 0
   mov   DWORD PTR [esp +12], 0
   call  edi
   mov   edx, [esi]
   test  edx, edx
   jz    Done
   ALIGN 4
NextString:
   sub   esp, 16
   sub   eax, eax
   mov   DWORD PTR [esp], ebp
   mov   DWORD PTR [esp + 4], LB_ADDSTRING
   mov   DWORD PTR [esp + 8], eax
   mov   DWORD PTR [esp +12], edx
   add   esi, 4
   call  edi
   cmp   eax, LB_ERRSPACE
   mov   edx, [esi]
   je    Done
   test  edx, edx
   jz    Done
   sub   esp, 16
   sub   eax, eax
   mov   DWORD PTR [esp], ebp
   mov   DWORD PTR [esp + 4], LB_ADDSTRING
   mov   DWORD PTR [esp + 8], eax
   mov   DWORD PTR [esp +12], edx
   add   esi, 4
   call  edi
   cmp   eax, LB_ERRSPACE
   mov   edx, [esi]
   je    Done
   test  edx, edx
   jnz   NextString
Done:
   pop   edi
   pop   esi
   pop   ebp
   ret   8
FillListBox ENDP

END

Want to know how FillListBox() works? Want to know where the comments went? Send e-mail on your company letterhead, and we'll talk about it. See the note below.

Mascot

FindL - find a long integer

int __stdcall FindL(
   long *,   // Long integer array
   int,   // Number of array elements
   long   // Value to find
   );

If you're writing lots of code in C/C++, you're writing long, convoluted switch blocks. After all, modern compilers optimize these into jump tables that execute quickly. Still, we have massive chunks of nearly-identical code--and the longer the code, the more complex it is, and the more likely we'll have problems with it later.

To the rescue is FindL(), a tiny Assembly language function that searches a long integer array for a value. Sure, you could write it in C, but before you decide to use a C version, look at a disassembly of it; in short: ugh. As well as compilers optimize, you'd think they could optimize this simple little function.

Here's an example using FindL:

const long Array[] = {27, 1, 93, 14, 0};
const char * Output[] = {
"Unknown value", // 0
"Twenty-seven",  // 1
"One",           // 2
"Ninty-three",   // 3
"Fourteen",      // 4
"Zero"};         // 5

return Output[ FindL(&Array,
  sizeof(Array) / sizeof(long),
  Value) ];

The FindL() function returns a 1-based index; if the value is not found, it returns zero. C expects zero-based indexes, so we're off by one--intentionally. In the example above, the string contains one extra element--the zero value. If the number isn't found (the default that follows the case tests), we still return a valid result, without unnecessary conditional tests (and conditional tests result in conditional jumps--which slow the processor to a crawl).

FindL Source Code

Written for Microsoft™ Visual C++ 4.0 or later and the flat memory model, this Assembly language code is optimized for Pentium and later processors:

// (C)2007 R.E.Harvey, All rights reserved
#ifdef _MSC_VER
__declspec(naked) int __stdcall
 FindL(int * MemPtr, int MemLen, int Value)
{
   __asm {
   mov   edx, edi
   mov   eax, [esp +12]  // Value
   mov   ecx, [esp + 8]  // MemLen
   mov   edi, [esp + 4]  // MemPtr
   repne scasd
   jnz   NotFound
   mov   eax, [esp + 8]  // MemLen
   mov   edi, edx
   sub   eax, ecx
   ret   12
   align 16
NotFound:
   sub   eax, eax
   mov   edi, edx
   ret   12
   }
}
#else
// C++ version here
#endif

This little function demonstrates several programming principles. It avoids pushing anything on the stack; it needs the EDI register, so it saves it in EDX, which is not used. It uses REPNE SCASD, which executes very quickly on Pentium-class computers. In the flat memory model, we assume the ES register is the same as the DS register. Integers, using int, are 32-bits; a pointer is the same size as an integer, and all pointers are near (including pointers to Windows DLL functions). The destination address of jumps, and it does use one, should be aligned; preferably on paragraph (16-byte) boundaries. Finally, there is no error return value; any result returned should be useful.

Ideally, we would add the inline directive, which would tell the preprocessor to expand each occurrence of the function to inline code. Unfortunately, when a function uses inline Assembly, most other compiler optimizations are disabled; for this reason, we have to use it as a function.

FindSI Function

Would you like a function that searched a short integer array for the low word of a long integer (such as looking for resource constants in Windows programs)? It's easy, just change the repne scasd to repne scasw. Here is the complete function:

// (C)2007 R.E.Harvey, All rights reserved
#ifdef _MSC_VER
__declspec(naked) int __stdcall
 FindSI(unsigned short int * MemPtr, int MemLen, int Value)
{
   __asm {
   mov   edx, edi
   mov   eax, [esp +12]  // Value
   mov   ecx, [esp + 8]  // MemLen
   mov   edi, [esp + 4]  // MemPtr
   repne scasw
   jnz   NotFound
   mov   eax, [esp + 8]  // MemLen
   mov   edi, edx
   sub   eax, ecx
   ret   12
   align 16
NotFound:
   sub   eax, eax
   mov   edi, edx
   ret   12
   }
}
#else
// C++ version here
#endif

The Array in the FindSI() version is declared unsigned, because resource constants may have values up to 65535.

TTFTest.exe

ttftest fontfile.ttf "Font Name" x

Applications often install fonts while they run, and uninstall the fonts when they stop running. In fact, this is the preferable (and polite) way to support custom fonts in programs. TTFTest, written in the C programming language, is designed as a torture-test for our custom fonts. It also demonstrates installing and uninstalling fonts. This program, including annotated source code, is available free of charge to our Custom Font customers.

Note:
You're thinking about it anyway, so here's permission for you to copy and paste the source code into your programming projects. You do not have the right to publish or sell or redistribute the source code. And, of course, nothing presented here is warranted for suitability or usability for any purpose whatsoever; use at your own risk. Lunch is available at extra cost. See Notice for additional limits. If you can't make it work, try a little harder. We offer consulting and development services for a fee.

Top | Notice | Home | | © Copyright 2007 R. E. Harvey, All rights reserved.