0

KDBG version: 3.0.1.

I have a 10x10 matrix defined in C, such as: char myArray[10][10] = { ' ', 'x', ... }, used on ASM.

In ASM I use the following line to compare the value of two chars:

cmp BYTE[myArray+rax], 'x'
inc rax

rax, initialized to 0 is used as loop counter and relative address displacement, both up to the number 100 (because the array in memory is 10*10=100 bytes long, right?)

So the idea is when rax is incremented by 1 (byte), in the cmp instruction I'm accessing the next element in myArray.

Now, in the KDBG Watched expressions panel, when using (&myArray+$rax) I expect to see the value of the element I'm accessing, yet I cannot accomplish that.

Tried:

  1. Independent from rax value:

&myArray, shows the starting address: (char)(*)[10][10] 0x5050a0 <myArray>, and some values comma separated. Can't tell if it is all of them.

  1. When rax=5, for example:

(&myArray+$rax), address: (char)(*)[10][10] 0x505294 <anotherArray+52>, there is a difference of 500 from the starting address and it is referencing another array I declared in C.

I'm not sure if this question is KDBG syntax related or my understanding of how arrays in asm work is wrong. Any help appreciated.

tec
  • 999
  • 3
  • 18
  • 40
  • 1
    `&myArray` is a pointer to the array, so adding one to the pointer will advance the pointer by the size of entire array. try `(myArray[0]+$rax)`. (I don't know KDBG, so this may be wrong) – MikeCAT Apr 01 '22 at 14:30
  • If `myArray` is declared in C as `char myArray[]..` then `myArray` is already an address, so `&myArray` would seem excessive, but maybe it works in that debugger. Maybe try `((char*)myArray)+$rax`, to convert `myArray` to byte pointer, then add $rax -- and perhaps deref that as in `((char*)myArray)[$rax]`. – Erik Eidt Apr 01 '22 at 16:06
  • @ErikEidt Hell yes! `((char*)myArray)[$rax]` DID IT! Do you mind to post an answer expanding your explanation? So I can better understand what's going on. The panel isn't showing the address but at least the value, and it is in effect, correct. – tec Apr 01 '22 at 16:26

1 Answers1

2

When an array is declared in C, the name of the array refers to the address of the whole array, which is the same value as the address of its first element.

In the case of your example, char myArray[10][10], the name myArray is the address of element myArray[0], aka &myArray[0].  If allowed, the construct &myArray would have the same value as myArray, but its type would change:

  • myArray has type char (*)[10], so the element size is 10
  • &myArray has type char (*)[10][10], so the element size is 100

In C, pointer arithmetic automatically scales the integer index by the element size, so myArray+$rax, which implies scaling should do myArray+$rax*10 with explicit scaling.  While &myArray+$rax would scale $rax by 100.

To neutralize the scaling, convert the pointer to a byte pointer — a byte pointer's element size is 1, so the implicit scaling effectively is suppressed (as 1 is the multiplicative identity).

The cast (char *) myArray converts the pointer to a byte pointer, then you can do byte pointer arithmetic effectively without C's scaling.

And the dereference with $rax will yield a byte element, so ((char*)myArray)[$rax].

Erik Eidt
  • 23,049
  • 2
  • 29
  • 53