, как ... Индекс позиции из массива ... ESI в качестве указателя
Сначала определение массива важно, если это простой плоский массив, состоящий из последовательных элементов, а затем получить индекс конкретного элемента, на который указывает адрес EDI
вы можете полностью изменить его вычислить из двух указателей, участвующих (это требует оригинальный указатель запуска из-массива еще в ESI
!):
mov eax,edi
sub eax,esi ; eax = (element_pointer - array_pointer)
; divide eax by <size_of_element>
; for example your OP code example suggest
; the array element size is DWORD = 4B
; then the division/4 can be done simply:
; shr eax,2
; for byte arrays there's no need to divide the address
; difference, eax already contains index, as BYTE size = 1B
; for other element sizes, which are *not* power-of-two
; (you can't divide the difference by simply shifting it right)
; it may be more efficient to address them through separate index
; or do the: imul/mul (1/el_size) || idiv/div el_size
; (when there's no way to avoid it)
; after division the eax contains 0, 1, ... index.
Если размер элемента нетривиальным (не степенным), или структура не является тривиальной (связанный список, поэтому разница двух указателей не коррелирует с индексом элемента), вы можете рассчитывать индекс отдельно. Тем не менее, чтобы избежать индекса mul element_size
индекса для каждой выборки, возможно, стоит смешать эти два, поэтому адресация через указатели и подсчет (бесполезный для выборки) индекса отдельно, который будет использоваться только для того, где вам нужен индекс.
Плюс в этом варианте можно индексировать от 1
, но я бы избежать этого, если это не какой-то человек выход для непрограммиста, так как большая часть ASM/C/C++ программисты, естественно, ожидающей индексацию начать в 0
(из-за в моем первом примере работает как-указатель-математика).
; stolen from Toommylee2k, then modified to focus on my explanation
xor ebx,ebx ; first index will be 1 (!)
; so I initialized ebx = 1 - 1 = 0, because
; I will increment it at beginning of loop
; for indexing from 0 the ebx should be initialized to -1
loop_start:
; update index first, so you can't miss it when branching later
lea ebx,[ebx+1] ; ebx = ebx+1 without flags modification
; since *here* "ebx" works as "index", contains "1" for first item
; do whatever you want with pointers, like "esi" in your sample code
; ...
; move to next element of array (avoids multiplication)
add esi,size_of_element
; although `imul` on modern CPU will perform quite close to `add`
; so when multiplication is unavoidable, go for it.
; the division on the other hand still costs very likely more
; than having separate register/variable for index counting
; loop till ecx is zero (in much faster way than "loop")
dec ecx
jnz loop_start
; "loop" is very slow due to historic reasons, to improve compatibility
И последнее продление, когда размер элемента является одним из [1, 2, 4, 8], вы можете использовать расширенный x86 режим адресации для работы с "0, 1, ..." индекс вместо чистых указателей:
mov ebx,7 ; index "7" = 8th element of array
lea esi,[array_of_words] ; array pointer
; addressing through index, supported directly by CPU for size 2
mov ax,[esi + ebx*2] ; complex x86 addressing allows this
; here ax = 8
...
.data
array_of_words:
dw 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
Если вы используете индексы в цикле довольно много, это может быть наиболее оптимальное решение. Если вам нужен индекс элемента только редко, чистые указатели обычно более оптимальны.
Count. Точно так же, как вы делаете с 'esi', но начинаете с 0 или 1 и делаете шаг 1. –
Вы не показываете, как определяется массив. В сборке определение и структура данных часто важнее самого кода. Без определения трудно определить, работает ли ваш код как есть, и может быть просто изменен, чтобы ответить на него, или он уже содержит некоторую ошибку (например, 'mov eax, [esi]' выглядит очень подозрительно .. но из 'add esi, 4' выглядит нормально). [mcve] очень важна для Ассамблеи. – Ped7g
Но ... думая об этом снова, может быть, этот вопрос имеет смысл без кода вообще, так как для домашней работы я нахожу действительным, если вы попросите метод/принцип, как его решить, чем для кода решений. – Ped7g