Версия KDBG: 3.0.1.
У меня есть матрица 10x10, определенная в C, например: char myArray[10][10] = { ' ', 'x', ... }
, используемая в ASM.
В ASM я использую следующую строку для сравнения значения двух символов:
cmp BYTE[myArray+rax], 'x'
inc rax
rax, инициализированный 0, используется как счетчик циклов и относительное смещение адреса, оба до числа 100 (поскольку массив в памяти имеет длину 10 * 10 = 100 байт, верно?)
Итак, идея в том, что когда rax увеличивается на 1 (байт), в инструкции cmp я обращаюсь к следующему элементу в myArray.
Теперь, на панели выражений KDBG Watched, при использовании (&myArray+$rax)
я ожидаю увидеть значение элемента, к которому я обращаюсь, но не могу этого сделать.
Пытался:
&myArray
, показывает начальный адрес: (char)(*)[10][10] 0x5050a0 <myArray>
и некоторые значения, разделенные запятыми. Не могу сказать, все ли это.
(&myArray+$rax)
, адрес: (char)(*)[10][10] 0x505294 <anotherArray+52>
, есть разница в 500 от начального адреса, и он ссылается на другой массив, который я объявил в C.
Я не уверен, связан ли этот вопрос с синтаксисом KDBG или мое понимание того, как работают массивы в asm, неверно. Любая помощь приветствуется.
Если myArray
объявлено в C как char myArray[]..
, то myArray
уже является адресом, поэтому &myArray
может показаться чрезмерным, но, возможно, это работает в этом отладчике. Может быть, попробовать ((char*)myArray)+$rax
, чтобы преобразовать myArray
в указатель байта, затем добавить $rax — и, возможно, удалить это, как в ((char*)myArray)[$rax]
.
@ErikEidt Черт, да! ((char*)myArray)[$rax]
СДЕЛАЛА ЭТО! Не возражаете ли вы опубликовать ответ, расширяющий ваше объяснение? Так я лучше понимаю, что происходит. На панели отображается не адрес, а, по крайней мере, значение, и оно действительно правильное.
Когда массив объявляется в C, имя массива относится к адресу всего массива, который является тем же значением, что и адрес его первого элемента.
В случае вашего примера char myArray[10][10]
имя myArray
является адресом элемента myArray[0]
, также известного как &myArray[0]
. Если разрешено, конструкция &myArray
будет иметь то же значение, что и myArray
, но ее тип изменится:
myArray
имеет тип char (*)[10]
, поэтому размер элемента равен 10.&myArray
имеет тип char (*)[10][10]
, поэтому размер элемента равен 100.В C арифметика указателей автоматически масштабирует целочисленный индекс по размеру элемента, поэтому myArray+$rax
, что означает, что масштабирование должно делать myArray+$rax*10
с явным масштабированием. В то время как &myArray+$rax
будет масштабироваться $rax
на 100.
Чтобы нейтрализовать масштабирование, преобразуйте указатель в байтовый указатель — размер элемента байтового указателя равен 1, поэтому неявное масштабирование эффективно подавляется (поскольку 1 является мультипликативной идентичностью).
Приведение (char *) myArray
преобразует указатель в указатель байта, после чего вы можете эффективно выполнять арифметические операции с указателем байта без масштабирования C.
И разыменование с помощью $rax
даст байтовый элемент, поэтому ((char*)myArray)[$rax]
.
&myArray
— это указатель на массив, поэтому добавление единицы к указателю сдвинет указатель на размер всего массива. попробуй(myArray[0]+$rax)
. (Я не знаю KDBG, так что это может быть неправильно)