Bin2Inc.exe | Snooze | FillListBox | FindL | FindSI | TTFTest | About | Home
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.
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.
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).
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.
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).
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.
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 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.