Wednesday, April 26, 2006

C: Linux Kernel Device Programming Article

Talk about taking the wind out of your sails… I came across this article on OSNews.com about Linux Kernel Device Driver programming, and the author used the exact same goal I was going to use, right down to using a parallel port driven LED test jig. This saves me an article I was going to research, and I look forward to trying this out firsthand without some of the hassles. All I have to say is… sweet.

Tuesday, April 25, 2006

Excel: Quick Macro to Set Selection Values to Negative

Here is a quick tip, lets say you have a Excel spreadsheet, and you quickly need to change a series of values to negative values. You can use the below macro, which demonstrates how to traverse through every cell in a selection and set the value to a negative value. This is useful for accounting formating.

Sub set_negative()
    Dim c As Range
    
    'For each cell in your selection
    For Each c In Selection
        'If the value is not blank, set to a negative version of
        'itself
        If (c.Value <> "") Then
            c.Value = c.Value * -1
        End If
    Next
End Sub

Monday, April 24, 2006

VB: Word Scramble using StrConv and StringBuilder

I had answered a fellow who wanted to know how you can write a word scramble in Visual Basic. For this problem, I will provide two examples, one in VB6, and the other in VB .Net. The VB6 version will simple take the string in a textbox and scramble the letters. The VB.Net version will take a string, separate each word, and scramble the words themselves. I thought this would be an interesting demonstration since working with character elements in VB strings has the tendency to be a bit of a pain. This will demonstrate using a character array to work with individual elements, using the StrConv function in VB6 to convert to a byte array, and using the StringBuilder class in VB.Net for more efficient string appends.

Below is the VB6 version 1:
Option Explicit
Private Sub CommandButton1_Click()
    Dim x, pos As Integer
    Dim char As String
    Dim s() As String
    
    'Re-dimension the array to the size of the string in the textbox
    ReDim s(Len(TextBox1.Text)) As String
    
    'Assign each character to an element in the array
    For x = 1 To Len(TextBox1.Text)
        s(x) = Mid(TextBox1.Text, x, 1)
    Next
    
    'For 1 to the size of the array, mix up the letters
    For x = 1 To UBound(s)
         'Pos is a random place in the array
               pos = Int((Len(TextBox1.Text) - 1) * Rnd) + 1
        
     'temporarily assign the temp character to our random letter
               char = s(pos)
        
     'Swap the characters, using the temp character to assign from the overwriten
     'element
        s(pos) = s(x)
        s(x) = char
    Next
    
    'Clear the textbox and concat the value with each element in the array
    TextBox1.Text = ""
    For x = 1 To UBound(s)
        TextBox1.Text = TextBox1.Text & s(x)
    Next
End Sub

Private Sub UserForm_Click()
    Randomize
End Sub

The above is a fairly simple. Take two elements in an array, and swaps them. This is pretty much the same as the VB.Net version below with a few exceptions. Alternatively, we can use the StrConv function to eliminate having to go through each element in the string and assign it to the array. This method is demonstrated below:

VB6 Version 2 Code:
Private Sub Command1_Click()
    Dim b() As Byte
    Dim temp As Byte
    Dim s As String
    Dim x, pos As Integer
    
    s = Text1.Text
    
    ReDim b(Len(s)) As Byte
    b = StrConv(s, vbFromUnicode)
    
    For x = LBound(b) To UBound(b)
        pos = Int((Len(Text1.Text) - 1) * Rnd) + 1
    
        temp = b(pos)
        
        b(pos) = b(x)
        b(x) = temp
    Next
    
    s = StrConv(b, vbUnicode)
End Sub


The above code is much cleaner in my opinion. In the StrConv() function, notice the use of the parameter vbFromUnicode and vbUnicode. The reason for this is that VB uses Unicode strings. Had we just assigned b the value of s, we would have an array twice as large, and the scramble code would need to take into account the additional byte that Unicode characters contain, otherwise we would have some undefined results.

Below is the VB .Net version 1. I used the first algorithm from above as the model:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'Initialize the random number generator
     Randomize()
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim s_array() As String = Split(TextBox1.Text, " ")
        Dim s, final As String
        Dim c As Char
        Dim x, i, pos As Integer

        'We need to cycle through the array of strings set in the dim statement above
        For x = LBound(s_array) To (UBound(s_array))

            'If the current place in the array is greater than the lower bound and less than or
            'equal to the last string, then we need to add a space in between words
            If (x > LBound(s_array)) And (x <= UBound(s_array)) Then
                TextBox1.Text = TextBox1.Text & " "
            End If

            'For each letter in the current word, cycle through and use a
            'simple character swap with a random position in the string
            For i = 0 To (s_array(x).Length - 1)
                'Get random position in the string
                pos = CInt(Int(s_array(x).Length * Rnd()))

                'Store the character so swap temporarily so it does not get lost
                c = s_array(x).Chars(pos)

                'Set current letter with the letter to get swapped
                s_array(x) = s_array(x).Insert(pos, s_array(x).Chars(i))
                s_array(x) = s_array(x).Remove(pos + 1, 1)

                'Set current letter to the stored letter, completing the swap
                s_array(x) = s_array(x).Insert(i, c)
                s_array(x) = s_array(x).Remove(i + 1, 1)
            Next

            'If we are on the first word, clear the textbox and set to current element
            'in the array, otherwise concat the textbox with current value
            If (x = LBound(s_array)) Then
                TextBox1.Text = s_array(x)
            Else
                TextBox1.Text = TextBox1.Text & s_array(x)
            End If
        Next
    End Sub
End Class

While the above code works, there are a few issues with it. First, just like in the VB6 version, the handling of individual characters is not clean. We can assign the string to an array of characters directly and be better off. Also, the use of inserts and removes for individual characters are ugly and inefficient. .Net strings are immutable, so for each insert and remove, a copy of the string is created, making things very slow. Fortunately .Net offers the StringBuilder class for doing just this sort of operation. Below is the modified .Net version taking advantage of the direct assignment to a character array and using the StringBuilder class.

Below is the Vb.Net code modified (Version 2):
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim s_array() As String = Split(TextBox1.Text, " ")
        Dim b() As Char
        Dim c As Char
        Dim x, i, pos As Integer
        Dim tmpStrngBldr As System.Text.StringBuilder = New System.Text.StringBuilder()

        'We need to cycle through the array of strings set in the dim statement above
        For x = LBound(s_array) To (UBound(s_array))

            'If the current place in the array is greater than the lower bound and less than or
            'equal to the last string, then we need to add a space in between words
            If (x > LBound(s_array)) And (x <= UBound(s_array)) Then
                tmpStrngBldr.Append(" ")
            End If

            b = s_array(x)

            'For each letter in the current word, cycle through and use a
            'simple character swap with a random position in the string
            For i = LBound(b) To UBound(b)
                'Get random position in the string
                pos = CInt(Int(UBound(b) * Rnd()))

                'Store the character so swap temporarily so it does not get lost
                c = b(pos)

                'Set current letter with the letter to get swapped
                b(pos) = b(i)

                'Set current letter to the stored letter, completing the swap
                b(i) = c
            Next

            ‘Store the swaped word in our stringbuilder
            tmpStrngBldr.Append(b)
        Next

        'assign the textbox the value in our string builder
        TextBox1.Text = tmpStrngBldr.ToString
        tmpStrngBldr = Nothing
    End Sub

Friday, April 21, 2006

VB: Annoying Joke Form

I came across a post in one of the beginners programming forums I read.  The programmer wanted to make a simple form, and when the user closed the form, it would continually pop-up additional forms with cute little messages of endearment (a-la the little programs that people would write and post on BBS’s back in the day when VB was first becoming popular. Other variations are the form that keeps moving when you click on the close button.) Although the purpose of the program in question is tasteless, I responded and helped the programmer with his task.

I am not sure which version of VB he was using, since this below code wouldn’t work in either VS.Net or Vb.Net 2003, but it is the code originally posted:

Public Class Form1
Dim joke As JokeForm
Dim intnewx As Integer = joke.Location.X
Dim intnewy As Integer = joke.Location.Y

Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing

joke = New JokeForm
joke.Show()

Randomize()
intnewx = (Rnd()) * 400
intnewy = (Rnd()) * 400

End Sub
End Class

There were a number of things I found that didn’t work. The assignment of joke.Location.X and Y in the declarations to intnewx and intnewy are incorrect for a number of reasons. The form joke is not even instantiated at this point, so the results would be undefined. From reviewing the code later, it looks like the programmer was trying to use intnewx and intnewy as pointers to the values of X and Y, however they are declared as integers, so the assignment of a value to them will not change the values. And the use of Location.X and Location.Y is not appropriate; it is easier to use form.left and form.top. The user wanted a loop, however it was not included, and once the joke form is created and shown, it would immediately be destroyed since the program is in the process of exiting at this point. If there was a loop, randomize would need to be called outside of it as well.

The final code ended up looking like this:

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Randomize()
    End Sub

    Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
        Dim joke As JokeForm
      
While (True)
            joke = New JokeForm

            joke.Show()

            joke.Left = CInt(Int((Windows.Forms.Screen.PrimaryScreen.WorkingArea.Width * Rnd()) + 1))
            joke.Top = CInt(Int((Windows.Forms.Screen.PrimaryScreen.WorkingArea.Height * Rnd()) + 1))

            joke = Nothing
        End While
    End Sub

A few things I did differently from the programmer. First, I called Randomize in the Form.Load method, which is better than calling Randomize each time you loop. I included an infinite loop (yuck) to keep the instantiated forms from being destroyed immediately. I also assigned the values to Left and Top after showing the form. I found that Visual Basic would override the position values if the values were assigned before show method is called. I converted the return from Rnd() to an integer since Rnd() will return a number between 0 and 1. I also used Windows.Forms.Screen.PrimaryScreen.WorkingArea.width and height as the lowerbound and upperbound values for the Rnd function, which will keep the new forms within the screen.

I can’t help but feel a little guilty for helping this guy out, but at the same time I am hoping he learned a little about VB programming from the experience. There are a number of interesting VB topics, such as how to instantiate forms, assigning values to position for forms, using the Randomize() and Rnd() functions, and although not advisable, how to put a program into an infinite loop. Although a bit juvenile, I seem to recall a little fake DOS prompt I once wrote in Pascal to make an individual think they typed “format c:”, so maybe juvenile behavior is a trend among young programmers.

Thursday, April 20, 2006

Microsoft Extends Visual Studio Express License Forever

I was very surprised when I found a link to this article on OSNews.com about Microsoft indefinitely extending their free license for Visual Studio Express. I have to admin, I thought it was a hoax at first, but sure enough, it looks like Microsoft is going to offer the Visual Studio Express line for free. This is good news for developers, as I have found that the free Express editions are pretty darn good development platforms, at least for the Windows environment. A few little things bug me, such as the inability to add features such as the Mobile SDK to them, but I can’t complain since the price is right. Now I don’t need to worry about my license expiring in a year since I really only have a passing interest in Windows development.

Friday, April 14, 2006

C++: Basic Random Numbers

Sometimes it is beneficial to generate random values in a program. This is good in cases like simulations and encryption. Someone asked me the best value to use to seed a random number generator. I don’t have a definitive answer, however I typically use the current system time to do so. After a little research, that seems to be the generally excepted standard. Srand() and rand() are pseudo random, meaning they aren’t truly random, so I don’t believe there is a “best” seed.

Here is a little bit on using random numbers in a program. Rand() is the function used in C to generate random numbers. It is defined in the Standard C Library. If the random number generator is not “seeded” with a value, it will generate the same values each time rand() is called. This is useful for developing and debugging so you can keep the same set of values with each successive call. However, in a real simulation, you may want the values to be a little more random. In which case, you will seed the random number generator with srand().

When generating random numbers, you should cap your values within an acceptable limit. For example, lets say you only need random numbers between 1 – 10. You will need to use the modulus operator with the cap value, which will return the remainder of the random value divided by the cap value. This will generate the numbers 0 – (MAX – 1), or 0 – 9 in this case. In order to get 1 through 10, you will need to add 1. Below is an example program that demonstrates using the random number generator to generate within a range of values. It will simulate 20 dice rolls with a 6-sided dice utilizing the random number generator.

#include <iostream>
#include <cstdlib> //needed for the rand function
#include <ctime> //needed to work with time

using namespace std;

int main()
{
     //The max random value we want generated frm the random number generator
     const unsigned char MAX_RANDOM_VALUE = 6;
     //The value to offset. rand will return values from 0 to (MAX_RANDOM_VALUE - 1)
     //so we need to offset it
     const unsigned char RANDOM_OFFSET = 1;
     int cnt; //our counter for our loop
     

     //We need to seed the random number generator using the current time
     //Current time is retrieved by calling time(0) OR time(NULL)
     srand(time(NULL));
     
     //we will loop through 20 rolls and return our results.
     //Notice the scaleing and shifting used in the random call...
     for (cnt = 1; cnt <= 20; cnt++)
          cout << "Roll number " << cnt << ": " << RANDOM_OFFSET + (rand() % MAX_RANDOM_VALUE) << endl;
     
     return 0;
}

Tuesday, April 11, 2006

Visual Basic: Integer to String/String to Integer Conversions

Someone asked how to convert from an integer to string in Visual Basic/VBA. The answer, Visual Basic will do this automatically. Observe the following code:

Sub test()
    Dim i As Integer
    Dim s As String
    
    i = 5
    s = i
    MsgBox s, vbOKOnly, "Test"
End Sub

In the above code, I will automatically be converted to a String, no extra code is necessary. Technically, it could be re-written as:

Sub test()
    Dim i As Integer
    
    i = 5
    MsgBox i, vbOKOnly, "Test"
End Sub

However, I feel that using the intrinsic functions of Val() and Str() are a little better since it clearly shows that you are converting from one type to another. Observe the below code:

Sub test()
    Dim i As Integer
    Dim s As String
    
    i = 5
    s = Str(i)
    MsgBox s, vbOKOnly, "Test"
    
    i = Val(s)
End Sub

Here, we can clearly tell by using the Str() function that we are converting from a number, and vice-versa with the Val() function. I feel that for clear understanding for future maintainers, this is a better approach. Interpreted languages such as VB and Perl that do automatic type conversion promote bad programming practices and I feel that type conversions such as this are a crutch for lazy programmers. I myself am guilty of this since I sometimes make exceptions when I am assigning a value to a textbox, however this is a habit I should break myself of. Programming isn’t just about writing code that works, it is also about writing code that can be maintained and understood by other developers.

Monday, April 10, 2006

Hex in Visual Basic

Someone asked me how could a Hex be represented in Visual Basic 6. Fortunately, there is a function that does this for us already. Its called Hex(), or Hex$(). It returns a string representing the hexadecimal equivalent of an integer. Of course, I prefer the C style representation of hex (either 0x00 or 00h), so I created a function that does this for me. Below is the code demonstrating this. For this, there is a small form with a textbox, a checkbox, and a label. The textbox will take in a number, the checkbox will determine which format to use, the long format of “0x00” or the short format of “00h”, and the label will display the result.

Option Explicit

Function convertToHex(n As Integer, longStyle As Boolean) As String
    If (longStyle) Then
        convertToHex = "0x" & Hex(n)
    Else
        convertToHex = Hex(n) & "h"
    End If
End Function

Private Sub Command1_Click()
    If (Check1.Value = Checked) Then
        Label1.Caption = convertToHex(Text1.Text, True)
    Else
        Label1.Caption = convertToHex(Text1.Text, False)
    End If
End Sub

Private Sub Form_Load()
    Text1.Text = &HFF
End Sub

Also notice in the Form_Load() method, I am hard coding the value of 255 (0xFF) into the textbox. The prefix of &H will force VB to take in Hex, but the value displayed in the textbox will be 255.

Thursday, April 06, 2006

Musing: Backlog of articles, and I'm thinking topics I’ve already thought about are great ideas.

I must be crazy, I added yet another topic to the “List of Topics” to write about. I have 70 unwritten articles. At least I know I don’t have a shortage of topics for a while. I came across a topic from November laying out an HTTP controlled bot similar to the Steganography bot. I thought this was funny since it was indicated by Georg 'oxff' Wicherski that this method is already used in the wild, and I responded and didn’t even remember marking this as something for further research. I think I need to start writing some of these articles and clearing the backlog.  

Wednesday, April 05, 2006

ASM/C++: Using inline ASM for Video Palette Manipulation in Turbo C++

Building off of the example of Video Programming with Turbo C++, I am going to use this program as a baseline to demonstrate how to do inline ASM with Turbo C++. For the version available from the Borland Museum, you will additionally need a copy of TASM to compile this program.

#include <dos.h>

int main()
{
     unsigned char red[256], blue[256], green[256], r, g, b;
     unsigned char far *VGA = (unsigned char *)MK_FP(0xA000, 0);
     unsigned int x, y;
     unsigned char z;
     struct time d;

     //set the video mode
     asm{
          mov ax, 13h
          int 10h
     };

     //load the sprawling palette
     for (x = 0; x <= 200; x++)
          for (y = 0; y < 320; y++)
               if (y <= 256)
                    VGA[(x * 320) + y] = y;
               else
                    VGA[(x * 320) + y] = y - 256;

     //Now load the palette into memory
     for (z = 0; z < 255; z++)
     {
          asm{
               //First, trigger the output port
               mov dx, 0x3c7
               mov ax, z
               out dx, al

               //Now read in the R, G, and B values, storing in
               //r, g and b respectively
               mov dx, 0x3c9
               in al, dx
               mov r, al
               in al, dx
               mov g, al
               in al, dx
               mov b, al
          }

          //Assign into the array
          red[z] = r;
          green[z] = g;
          blue[z] = b;
     }

     //What this will do is fade red out first, then blue, then green
     //X controls which color is fading, y controls the intensity, and
     //z is controlling which palette entry we are changing
     for (x = 0; x < 3; x++)
          for (y = 0; y < 64; y++)
               for (z = 1; z < 255; z++)
               {
               //based on the color to fade, subtract that color
               switch (x)
               {
               case 0:
                    if (red[z] > 0)
                         red[z]--;
                    break;
               case 1:
                    if (green[z] > 0)
                         green[z]--;
                    break;
               case 2:
                    if (blue[z] > 0)
                         blue[z]--;
                    break;
               } //end switch

               //set r, g, and b for output in ASM
               r = red[z];
               g = green[z];
               b = blue[z];

               //port 3c8 signals 3c9 to recieve a new palette
               //entry for color z
               asm{
                    //trigger the port for palette output
                    mov dx, 0x3c8
                    mov ax, z
                    out dx, al

                    //output the palette respectively
                    mov dx, 0x3c9
                    mov al, r
                    out dx, al
                    mov al, g
                    out dx, al
                    mov al, b
                    out dx, al
               }
               } //end for

     //set video mode back to 80x25
     asm {
          mov ax, 3h
          int 10h
     };

     return 0;
}

The main changes are the inclusion of inline ASM for manipulating the palette, similar to the method demonstrated with this debug program. The only issue I had with doing this was I could not directly pass the array values into the inline asm, so I had to create the temporary variables r, g, b to store the values to pass. Each time I tried, I got an “invalid index” error. I also used the Borland declaration MK_FP to point to the VGA memory to demonstrate an alternative method of doing so from the previous example. And one very important note, be sure to use unsigned integers rather than integers, as this caused a few undefined results when I initially wrote both programs.

Inline ASM differs greatly between the more inline friendly Borland suites and the GCC family. In GCC, inline asm it basically a function call like so:

asm(“asm code”, output operands, input operands, registers that get “clobbered”);

More information on GCC Inline Assembly can be found here, here, and here. The last link is for DJGPP, a GNU-like compiler for DOS and Windows, but the syntax and information is still valid for GCC.

Monday, April 03, 2006

Tech: Microsoft to free Virtual Server

Here is an interesting tidbit. Microsoft plans to offer Virtual Server for free (as in price, not as in freedom). Although they state it has little to do with Xen being built into RedHat and Suse, I imagine that VMWare offering GSX for free has something to do with it. I will be honest though, I have no intention of using Virtual Server since it is not cross platform, and the performance of VMWare is just top notch in my experience. But I might mess with it to get a feel for it. It just goes to show you that Virtualization is a hot technology, but it might soon become commodity.

C++/DOS: Video Programming with Turbo C++

I decided to build off of the Assembly example demonstrated here to show the same basic program written in a higher-level language. This program will make the same sprawling palette, then fade it out to black. The program was written in Turbo C++ 1.01, which is available for free under Borlands Antique Software Museum.

//dos.h is used to for the interupt calling functions, registers structure,
//and for input/output functions
#include < dos.h >

int main()
{
     //Used to store the palette entries. This could have easily
     //been done as a 3 dimensional array, but I feel conceptually
     //it is easier to use 3 seperate arrays for red, blue, and green
     unsigned char red[256], blue[256], green[256];

     //A far pointer used to work directly with the VGA screen memory
     //unsigned char far *VGA = (unsigned char *)MK_FP(0xA000, 0); //alternate declaration
     unsigned char far *VGA = (unsigned char *) 0xA0000000L;

     //counters, make sure they are unsigned
     unsigned int x, y, z;

     //used to represent the CPU registers, provided by dos.h
     union REGS regs;

     //set the registers for Interupt 10h, function 0, mode 13h
     //and call the interrupt to set the video mode to 320x200 256 colors
     regs.h.ah = 0;
     regs.h.al = 0x13;
     int86(0x10, ®s, &regs);

     //load the sprawling palette onto the screen
     for (x = 0; x < 200; x++)
          for (y = 0; y < 320; y++)
               //since the palette is only 256 colors, loop back
               //to the first color after 320
               if (y < 256)
                    VGA[(x * 320) + y] = y;
               else
                    VGA[(x * 320) + y] = y - 320;

     //Now load the palette into memory. This will allow
     //us to manipulate the palette in memory and load into
     //the palette rather than having to read, change, then write
     //from the video ports
     for (x = 0; x < 255; x++)
     {
          //port 3c7 signals palette read from port 3c9
          outp(0x3c7, x);

          red[x] = inp(0x3c9);
          green[x] = inp(0x3c9);
          blue[x] = inp(0x3c9);
     }

     //What this will do is fade red out first, then blue, then green
      //X controls which color is fading, y controls the intensity, and
      //z is controlling which palette entry we are changing
      for (x = 0; x < 3; x++)
           for (y = 0; y < 64; y++)
                for (z = 1; z < 255; z++)
               {
                    //based on the color to fade, subtract that color
                    switch (x)
                    {
                         case 0:
                              if (red[z] > 0)
                                    red[z]--;
                               break;
                         case 1:
                              if (green[z] > 0)
                                   green[z]--;
                              break;
                         case 2:
                              if (blue[z] > 0)
                                   blue[z]--;
                               break;
                         } //end switch

                    //port 3c8 signals 3c9 to recieve a new palette
                    //entry for color z
                    outp(0x3c8, z);
                    outp(0x3c9, red[z]);
                    outp(0x3c9, green[z]);
                    outp(0x3c9, blue[z]);
               } //end for

     //switch screen mode back to 80x25 text
     regs.h.ah = 0;
     regs.h.al = 0x3;
     int86(0x10, ®s, &regs);

     return 0;
}

The program touches on a few interesting points. It demonstrates how to communicate with hardware ports using the old DOS architecture and Turbo C++. It also demonstrates how pointers can be used to directly access hardware memory points, such as the VGA memory. It also demonstrates how to call DOS and hardware interrupts in a higher-level language using the dos.h header file. Something like this could have been written in assembler, however it would have been very difficult. In my next article, I will show how C++ and inline assembly can be used to accomplish the same task.