如何...索引位置數組...... 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
它可能是值得的混合兩個,所以通過指針尋址,並單獨計數(無用的提取)索引,這將只用於你需要索引的東西。因爲大多數ASM/C/C++程序員自然希望在0
處開始編制索引(歸因於以下原因):在我的第一個例子中,how-pointer-math是如何工作的)。
; 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
如果您在循環中使用索引很多,這可能是最佳的解決方案。如果你只需要很少的元素索引,純指針通常會更優化。
計數。就像你用'esi'做的一樣,但是從0或1開始,然後按1步進。 –
你不顯示數組是如何定義的。在Assembly中,定義和數據結構通常比代碼本身更重要。如果沒有定義,很難判斷代碼是否工作正常,並且可以修改爲回答您,或者它是否已經包含一些錯誤(例如'mov eax,[esi]'看起來高度可疑......但是從add esi,4'看起來沒問題)。 [mcve]對Assembly來說非常重要。 – Ped7g
但是......再想一遍,也許這個問題在沒有代碼的情況下變得更有意義,因爲如果您要求方法/原則,如何解決問題,我認爲這些作業比解決方案代碼更有意義。 – Ped7g