tec
tec

Reputation: 1147

KDBG ASM view array element address and value with relative address displacement

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.

Upvotes: 0

Views: 123

Answers (1)

Erik Eidt
Erik Eidt

Reputation: 26646

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].

Upvotes: 2

Related Questions