September Twenty-Eighth 2009 From: Bob Zale, President PowerBASIC, Inc. PowerBASIC Gazette #69 ====================== Subject: Windows Programming Hints ================================== Obviously, our staff programmers have quite a bit of experience with the intricacies of Windows. They deal with it daily and have some interesting tips they'd like to share. Stay tuned! HEX Conversions =============== It isn't long before every programmer needs to deal with HexaDecimal numbers. You may need to convert an integer value to a string with hex representation -- for that, PowerBASIC gives you the HEX$() function. It's very good, with display options and a very large capacity. Other times, you need the reverse functionality: convert a string of hex digits to their real value, assigning it to a variable. That's easy, too. Just prepend "&H" to the hex string and use the VAL() function. For example, this code will do it... h$ = "FF" x& = VAL("&H" + h$) The result? x& now contains the value 255 (decimal), the equivalent of &HFF. But sometimes, you just don't need the frills and the capacity for very large numbers. Very often, we just need to convert one byte or one nybble (a half-byte) to its ASCII string equivalent. You might even be in the middle of some ASM code where it's inconvenient to call a PowerBASIC function. So, what to do? Well, you could just convert it yourself. How many of us have already written this code in assembler? First, mask off half of a byte value (a nybble) with the AND operator. Check if the value is less than ten. If so, map that value to the equivalent ASCII characters "0" to "9". But, if it's ten or greater, map it to the ASCII characters "A" to "F". Then, retrieve the original unmasked value -- shift it, mask the high nybble, and do it all again. This works, but it sure is messy! So, check out this alternative... Bin4ToHex: ASM add al, 90h ASM daa ASM adc al, 40h ASM daa These four ASM opcodes will convert a nybble (a value in the range of 0 to 15) in register AL to its ASCII hex eqivalent, "0" to "9" or "A" to "F". Yes, it's just that easy! Need more digits? Bin8ToHex: push eax ror al, 4 call Bin8a pop eax Bin8a: and al,00001111b add al,90h daa adc al,40h daa stosb ret Just call this subroutine one or more times. Each time, enter with register AL containing a value in the range of 0 to 255. The two resulting hex characters are stored at the consecutive memory locations pointed to by register EDI. Be sure the direction flag is clear, or add a CLD opcode at the start. Windows and the Direction Flag ============================== The Intel CPU offers numerous opcodes that perform string operations with automatic repeat options (STOSB, MOVSW, SCASD, etc.). They act on a memory location, increment or decrement the memory pointer, then do it again for a defined number of operations. The CPU makes the choice to either increment or decrement based upon the "Direction Flag", which is maintained in the CPU. If the direction flag is cleared, the memory pointer is incremented. If it is set, the memory pointer is decremented. The default condition for the Direction Flag is clear. Although it isn't well documented, Windows expects it to be in a clear condition during every function call to the Windows API. If this rule is ever broken, you invite disaster, GPF's, and a sense of Armageddon . Generally speaking, PowerBASIC protects this state 100% of the time. The only exception is inline ASM code, where the programmer has total control. Please use caution. So, the rule is this: If you ever execute a STD (Set Direction Flag) with ASM, be absolutely certain to execute a CLD (Clear Direction Flag) before you exit that code block. That will keep you "in the clear"! Windows and Stack Alignment =========================== The Stack Pointer Register (ESP) is always DWORD-Aligned when a program begins execution. That is, the value in ESP is evenly divisible by four. Once again, though not well documented, it's essential that ESP remain DWORD-Aligned at all times. If you ever make a function call to the Windows API without that alignment, you risk a complete system failure. When you execute compiled BASIC code, PowerBASIC manages this for you. But with inline ASM code, this onus is on the programmer. In most cases, this is caused by PUSH/POP of 16-bit registers... ASM PUSH DX ASM CALL Win_Function ASM POP DX Since the DX register is only 16-bits wide, DWORD-Alignment is destroyed, and your program is doomed. Don't do it. PUSH and POP the 32-bit EDX register instead, or PUSH and POP registers in pairs. ==================================================================== Is your PowerBASIC Gazette Electronic Edition subscription coming to you at home or work? If you don't want to miss a single issue, why not subscribe from both email addresses? Send your subscription request to email@powerbasic.com and please include your name and all email addresses you'd like to add as well as your Zip or Postal Code. If you know someone else who would enjoy this newsletter please forward a copy to them so they can subscribe. ==================================================================== All contents Copyright (c) 2009 PowerBASIC Inc All Rights Reserved. PowerBASIC, PB/CC, PB/DLL, PowerGEN, and PowerTREE are trademarks of PowerBASIC Inc. Other names are trademarks or registered trademarks of their owners. ==================================================================== PowerBASIC Gazette - Electronic Edition Volume 1 - Issue 69 PowerBASIC, Inc. (888) 659-8000 Sales 2061 Englewood Road (941) 473-7300 Voice Englewood, FL 34223 (941) 681-3100 Fax Visit us on the World Wide Web at http://www.powerbasic.com Email Sales: sales@powerbasic.com This newsletter is only sent to email addresses in our subscription list. If you have received this newsletter by mistake or no longer wish to receive it, please send a simple unsubscribe request to support@powerbasic.com with your name and zip/postal code. This newsletter is best viewed with a fixed-width font. ====================================================================