2016-07-13 56 views
1

註釋上面說:從內存ADRESS A. N個數的計算的代碼只是爲了教育目的...彙編:瞭解如何計算代碼的平均

我想明白是怎麼一個平均值的計算工作在彙編程序中。守則評論由我撰寫。如果我理解錯誤,請將其添加到您的答案中。我不瞭解的部分尤其是ADD EBX,4

該代碼的目的是獲得內存地址A中所有數字的平均值。請仔細閱讀評論。

MOV ECX, [N]  ;Loading count of numbers in ECX 
JZ done   ; If the count of numbers is 0 go to done 
MOV EBX, [A]  ; Load all the numbers which are in memory space [A] in EBX 
MOV EAX,0   ; EAX will be the result 
Loop: ADD EAX, [EBX] ;Add first number of EBX to EAX? 
ADD EBX, 4   ;What is this doing and how does it work, why would you add the number 4? 
DEC ECX    ;Numbers to add - 1 
JNZ Loop    ;Jump if not zero, and repeat the loop 
DIV [N]    ;Divide the result of the calculation 
Done: ;value of average in EAX 

這些問題在代碼註釋中。 向我提供什麼[A][N]是什麼以及它們是如何工作的,特別是ADD EBX,4正在做什麼?謝謝。

+2

8086/8088沒有像_ECX_這樣的32位寄存器, _EBX _,_ EAX_。這些16位處理器支持16位版本_CX_,_AX_,_BX_(以及高/低字節部分)。 –

+2

假設這實際上是386代碼,那麼'ADD EBX,4'將遍歷一個DWORD數組(32位值)。一個DWORD是32位寬(4字節)。因此,要從一個DWORD轉到下一個,每次迭代時必須在_EBX_中將地址添加到4。 'ADD EAX,[EBX]'在_EBX_指向的內存地址處獲取DWORD值並將其添加到_EAX_中的值,將添加的結果存儲在_EAX_ –

+0

@MichaelPetch中需要了解的內容,該代碼僅供教育目的。我不知道它在哪個處理器上工作,即使它在一個類處理器上工作:( –

回答

1

讓我們先從變量的定義中的「N」和「A」,他們是這樣的:

.data 
    N  dd 5 
    ARRAY dd 1,2,3,4,5 
    A  dd ? 

我們現在的「N」是因爲在你的代碼「N」輸入「DD」表示被分配給寄存器「ECX」,它的尺寸爲32位:

MOV ECX, [N]  ;Loading count of numbers in ECX 

「A」是一個指向數字(如@MichaelPetch指出)的陣列,因爲寄存器「EBX」被設定爲「[ A]「,並在每個循環中將其值添加到EAX:

mov [A], offset ARRAY  ;A IS THE ADDRES OF THE ARRAY OF NUMBERS. 
MOV EBX, [A]    ;IN IDEAL MODE VARIABLES VALUE IS ACCESSED WITH BRACKETS. 
... 
Loop: ADD EAX, [EBX] ;Add first number of EBX to EAX? 

順便說一句,在標有「loop:」可能是一個問題,因爲這是一個指令的名字,讓我們改名字「糊塗」:

Loopy: ADD EAX, [EBX] ;Add first number of EBX to EAX? 
... 
JNZ Loopy    ;Jump if not zero, and repeat the loop 

註冊「EBX」工作原理一個指針,指向號碼的「陣列」的數組:

mov [A], offset ARRAY ;A IS THE ADDRES OF THE ARRAY OF NUMBERS. 
MOV EBX, [A]   ; Load all the numbers which are in memory space [A] in EBX 

此指針必須被向前移動時,在第一時間它指向「1」(用「A」指出在陣列「陣列」的第一個數字) ,爲了使它指向其餘的數字,我們必須在每個循環中加上「4」,因爲數組「ARRAY」(由「A」指出)是類型「d」 d」,這意味着每個元素的大小爲4個字節:

ADD EBX, 4   ;What is this doing and how does it work, why would you add the number 4? 

最後,除以 「[N]」:

DIV [N]    ;Divide the result of the calculation 

的 「DIV」 指令,當該值是 「DD」採用「EDX」還註冊,所以這將是一個很好的idead以清除「EDX」,以避免錯誤的結果:

MOV EDX, 0 
DIV [N]    ;Divide the result of the calculation 

現在,「EDX」爲0時,該司將分爲「EAX」而已,得到平均值。

+2

認爲'MOV EBX,[A]'表明A是一個指向DWORDS數組的指針?如果'A'是指向數組的實際指針,我希望指令爲'LEA EBX,[A]'? –

+0

@MichaelPetch,像往常一樣,你是對的。 –

+1

隨着你的edi t,難道你不能在編譯時將ARRAY的地址放入變量A中。像「A dd ARRAY」之類的東西?目前還不清楚這是否是使用32位寄存器的16位代碼(指針是16位文字),還是32位地址的32位代碼。如果它是32位代碼A應該是'DD'而不是'DW'? –

2
MOV ECX, [N]  ;Loading count of numbers in ECX 
JZ done   ; If the count of numbers is 0 go to done 

第二個評論是錯誤的。 mov不會改變ZF,所以條件跳轉將發生在來自調用者的ZF值上。

爲了有一個代碼工作的意見建議,你就必須測試這樣的牽強值:

MOV ECX, [N]  ;Loading count of numbers in ECX 
TEST ecx,ecx  ; do virtual "AND ecx,ecx" and set only flags 
JZ done   ; If the count of numbers is 0 go to done 

或者CMP ecx,0,或JZ可以通過JECXZ無需設置ZF所取代。 (或者可能是百萬其他神祕的方式,當ecx爲零時如何設置一些標誌,而不會改變它的內容......沒有人提及OR ecx,ecx ...)

+1

請不要提及'或ecx,ecx',這是愚蠢的,因爲它不能與條件分支進行宏觀融合。並且在ecx可以被下一條指令使用之前增加一個等待週期。是的,有無數的方法可以做到,但'test/jz'是唯一的好方法:P。或者'jecxz'在某些CPU上並不可怕。 –