Thread: Stumped on old 16-bit code

  1. #1
    Registered User
    Join Date
    Jun 2009
    Posts
    93

    Stumped on old 16-bit code

    I've been trying to decipher this piece of old 16-bit Windows code and I just can't get it. The code was originally written in C and shown here interpreted by SoftIce; I guess a loose form of Assembly. The code fragment below is a loop; that I do know; which was confirmed in the IDA dissasembler. My comments are shown within "/* */". Any insight on how to transform this back to C would be greatly appreciated.

    Code:
    sub  ax ,ax        /* clear AX  AX=0000 */
    mov  [03DF], ax    /* put 0 in global variable int [03DF] */
    mov  [bp-14], ax    /* start loop  for (bp-14 = 0; bp-14 >= 8; bp-14++) */
    jmp  0752          /* takes the jump */
    0752: cmp  word ptr [bp-14], 08    /* bp-14 >= 8 part of "for" loop */
    jge  0784         /* no jump  jge tells me that [bp-14] is a "signed" int or "signed" word */
    mov  bx, [bp-14]    /* not a clue since [bp-14] is an int and "bx" register usually refers to pointers */
    shl  bx, 02        /* bx*4   EBX=0000 */
    add  bx, [03D0]    /* bx+[03D0]  global variable int [03D0] is equal to 0 */
    shl  bx, 1         /* bx*2 */
    push  ds           /* the up coming global variable [034E] is possibly a (char *)?? */
    push  word ptr [bx+034E]   /* finished product for operand 1 for lstrcmpi...DS:034E=0222 */
    lea  ax, [bp-12]           /* local variable char [bp-12]  operand 2 for lstrcmpi */
    push  ss
    push  ax
    call  lstrcmpi
    or  ax, ax       /* lstrcmpi statement must be conditional...maybe  if (lstrcmpi(operand 1, operand 2) == 0) */
    jnz  074F           /* no jump   BTW, AX=0000; EBX is still 0000 */
    mov  bx, [bp-14]    /* again clueless since [bp-14] is an int */
    shl  bx, 03         /* bx*8 */
    mov  ax, [bx+0354]   /* put [bx+0354] in AX...which BTW everything is equal to 0  */
    mov  [03DF] ax       /* put AX in [03DF]....which BTW means zeros for everyone */

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    I would guess that bp-14 represents an array index, perhaps. strcmpi is "case-insensitive strcmp" so the two arguments there had better be pointers-to-char, not chars themselves. 03D0 had better contain the base address of the array then. strcmpi returns negative/0/positive just like strcmp, so your or ax,ax does exactly what you think it does.

  3. #3
    Registered User
    Join Date
    Jun 2009
    Posts
    93
    03D0 is a INT global variable which is the resultant of the statement:
    Code:
    03D0 = GetProfileInt(szIntl, "iDate", 0);
    I agree about lstrcmpi only working with strings, so somehow operand 1 needs to be (char) related. If [bp-14] and [03D0] are both INT's then that only leaves [034E] as a (char) I guess?..Somehow. So, I'm thinking something like: 034E[bp-14*4+03D0*2]. And then in the lstrcmpi call operand 1 "034E" is referenced as a (char * )???
    Last edited by TAZIN; 12-12-2010 at 12:02 PM.

  4. #4
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    cmp word ptr [bp-14],
    This is telling me that bp-14 is an array index into an array of words. Perhaps SoftIce is mis-reading something and using an int as a char.

  5. #5
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    I wrote 03D0, but that's because I somehow was looking back at the wrong line. The actual fetch uses 034E, not 03D0. So that's going to be your base address.

    And I would guess the bottom sets up the return value? And 0354+bx looks like it might be an array-addressing thing as well, since bx = 8*index value?

  6. #6
    Registered User
    Join Date
    Jun 2009
    Posts
    93
    I'm kinda sure that [bp-14] is a signed INT or WORD since it's refered to in other parts of the module as:
    Code:
    mov  word ptr [bp-14], 0
    inc  word ptr [bp-14]
    I guess the bottom part could be something like: 03DF = 0354[bp-14*8]....

  7. #7
    Registered User
    Join Date
    Jun 2009
    Posts
    93
    Ok, it looks like this loop is designed to compare two date pictures. One being the mess surrounding [034E], and the other stored in [bp-12]. The mess around [034E] gets one of its parameters from the function call GetProfileInt "iDate" which is set to default "0" meaning Month-Day-Year. Local char [bp-12] ends up being "M/d/yy" after a few statements prior to the code segment I posted. So, is there any way to re-construct this mess back to C given this information?

  8. #8
    Registered User
    Join Date
    Oct 2008
    Posts
    1,262
    It seems to me to be something like:
    Code:
    int mem_03df = 0;
    char somebuffer[???]; /* Starts at [bp-12], length unknown */
    int i; /* [bp-14] */
    int bx;
    
    for(i = 0; i < 8; ) {
    	bx = mem_034e[i*4 + mem_03d0];
    	/*
    		Probably:
    		bx = mem_034e[i][mem_03d0];		
    	*/
    	if(lstrcmpi(somebuffer, bx) == 0)
    		break;
    }
    
    mem_03df = mem_0354[i*4];
    But it's extremely hard without being able to debug or know more about the values at runtime and where they come from.
    Last edited by EVOEx; 12-12-2010 at 05:32 PM.

  9. #9
    Registered User
    Join Date
    Jun 2009
    Posts
    93
    Thanks EVOEx for the response. I too was thinking of something similiar after an array was suggested earlier.

    Code:
    int iTmp = 0;       /* [03DF] */
    char szBuffer[];    /* [bp-12] */
    int i;              /* [bp-14] */
    int iVal[];         /* [0354] */
    char szTemp[];      /* [034E] */
    
    for (i = 0; i < 8; i++)
    {
        if (lstrcmpi(szTemp[i*4 + iTmp*2], szBuffer) == 0)
            break;
    }
    
    iTmp = iVal[i*8];
    Now that I think about it, the way I show it a char array wouldn't work for operand 1 in the lstrcmpi function.....I think the compiler would through a error or warning.
    Last edited by TAZIN; 12-12-2010 at 08:00 PM.

  10. #10
    Registered User
    Join Date
    Oct 2008
    Posts
    1,262
    Quote Originally Posted by TAZIN View Post
    Thanks EVOEx for the response. I too was thinking of something similiar after an array was suggested earlier.

    Code:
    int iTmp = 0;       /* [03DF] */
    char szBuffer[];    /* [bp-12] */
    int i;              /* [bp-14] */
    int iVal[];         /* [0354] */
    char szTemp[];      /* [034E] */
    
    for (i = 0; i < 8; i++)
    {
        if (lstrcmpi(szTemp[i*4 + iTmp*2], szBuffer) == 0)
            break;
    }
    
    iTmp = iVal[i*8];
    Now that I think about it, the way I show it a char array wouldn't work for operand 1 in the lstrcmpi function.....I think the compiler would through a error or warning.
    Well, you'll have to find out what the array it's compared with/read from is to understand what this function does. But your last line of code is wrong though: iVal is an array of 16 bits items (char pointer is my guess). So "i*8" should actually be "i*4".

  11. #11
    Registered User
    Join Date
    Oct 2008
    Posts
    1,262
    Quote Originally Posted by EVOEx View Post
    It seems to me to be something like:
    Code:
    int mem_03df = 0;
    char somebuffer[???]; /* Starts at [bp-12], length unknown */
    int i; /* [bp-14] */
    int bx;
    
    for(i = 0; i < 8; ) {
    	bx = mem_034e[i*4 + mem_03d0];
    	/*
    		Probably:
    		bx = mem_034e[i][mem_03d0];		
    	*/
    	if(lstrcmpi(somebuffer, bx) == 0)
    		break;
    }
    
    mem_03df = mem_0354[i*4];
    But it's extremely hard without being able to debug or know more about the values at runtime and where they come from.
    Note by the way that mem_0354 overlaps with mem_034e. In fact, it's +6. So the code should be:

    Code:
    int mem_03df = 0;
    char somebuffer[???]; /* Starts at [bp-12], length unknown */
    int i; /* [bp-14] */
    int bx;
    
    for(i = 0; i < 8; ) {
    	bx = mem_034e[i*4 + mem_03d0];
    	/*
    		Probably:
    		bx = mem_034e[i][mem_03d0];		
    	*/
    	if(lstrcmpi(somebuffer, bx) == 0)
    		break;
    }
    
    mem_03df = mem_034e[i*4 + 3];
    /*
    Probably:
    mem_03df = mem_034e[i][3];
    */

  12. #12
    Registered User
    Join Date
    Jun 2009
    Posts
    93
    I think that if [0354] were a (char) or (char * ) then you'd end up with something like:
    Code:
    mov  bx, [bp-14]
    shl  bx, 03
    mov  al, [bx+0354]
    cbw
    mov  [03DF] ax
    The same would hold true I'd guess if [034E] were used since it's (char) based. I was under the impression that in 16-bit code (char) or (char * ) was 8-byte and therefore used the AL register, whereas and INT was 16-byte and used the AX register. That's why I choose an INT array for [0354].

  13. #13
    Registered User
    Join Date
    Oct 2008
    Posts
    1,262
    Quote Originally Posted by TAZIN View Post
    I think that if [0354] were a (char) or (char * ) then you'd end up with something like:
    Code:
    mov  bx, [bp-14]
    shl  bx, 03
    mov  al, [bx+0354]
    cbw
    mov  [03DF] ax
    The same would hold true I'd guess if [034E] were used since it's (char) based. I was under the impression that in 16-bit code (char) or (char * ) was 8-byte and therefore used the AL register, whereas and INT was 16-byte and used the AX register. That's why I choose an INT array for [0354].
    034E (and 0354) is arrays of pointers to strings or, more likely, an array of array of strings. I think it looks like:
    Code:
    char something[8][2];
    Or so.

  14. #14
    Registered User
    Join Date
    Jun 2009
    Posts
    93
    Well, I decided to try some of the suggestion offered within this post, so I fired up an old computer and loaded an old Microsoft compiler. Here's some results:
    Code:
    char something[] [] <-- using this produced whats below
    int iVal;  /* [03DF] */
    
    /* iVal = something[i][3]; */
    
    imul  bx, [bp-6], 2C
    mov   al,[bx,06D3]
    cbw
    mov   [545E], ax
    /*****************/
    
    int something[] <--- using this produced this
    int iVal;  /* [03DF] */
    
    /* iVal = something[i*4 + 3]; */
    
    mov  bx, [bp-6]
    shl  bx, 3
    mov  ax, [bx+06D6]
    mov  [53FA], ax
    So, my assumption was correct in that a (char) based array would use AL rather than AX. BTW, the part for the lstrcmpi statement was kinda close, but still interjected the AL register because of the (char) based array.

  15. #15
    Registered User
    Join Date
    Oct 2008
    Posts
    1,262
    Quote Originally Posted by EVOEx View Post
    034E (and 0354) is arrays of pointers to strings or, more likely, an array of array of strings. I think it looks like:
    Code:
    char something[8][2];
    Or so.
    Sorry, I made an typo in the code of this post (not in the explanation above it). The code should be (as I said an array of arrays of strings):
    Code:
    char *something[8][2];
    Try that, that should produce code like that.
    Note that the "8/2" are probably wrong as well, but I didn't bother to actually look into exactly what those values should be (think it should be 8/4).
    Last edited by EVOEx; 12-14-2010 at 06:22 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Hamming code / even parity help
    By Striker9 in forum C++ Programming
    Replies: 1
    Last Post: 10-02-2009, 09:14 PM
  2. How does 0xff get represented on a 16 bit machine?
    By Overworked_PhD in forum C Programming
    Replies: 2
    Last Post: 10-27-2007, 11:32 AM
  3. 16 bit MS-Dos Subsystem Prob
    By darkmessiah in forum Windows Programming
    Replies: 2
    Last Post: 07-10-2005, 11:37 AM
  4. SSH Hacker Activity!! AAHHH!!
    By Kleid-0 in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 03-06-2005, 03:53 PM
  5. Interface Question
    By smog890 in forum C Programming
    Replies: 11
    Last Post: 06-03-2002, 05:06 PM