2015-11-16 148 views
-1

作爲一個彙編代碼的初學者,我很困惑movs。從y開始的九個字節的結果內容是('a','b','c','a','b','c','a','b','c'),但我不知道爲什麼。我知道movs是從一個內存複製到另一個,但下面的代碼是如何工作的?彙編代碼MOVS

1 .data 
2 x: .string "abcde" # 5 characters plus a null 
3 y: .space 9 
4 
5 .text 
6 .globl _start 
7 _start: 
8 movl $x, %esi    #esi point to x as source 
9 movl %esi, %edi   #edi point to x as destination 
10 addl $3, %edi    #why we add 3 to edi? 
11 movl $6, %ecx    #counter 
12 rep movsb     #what does it exactly do? 
13 done: 

回答

3

指令的工作原理是如何寫入指令集的引用。

addl $ 3,%edi#爲什麼我們加3到edi?

調整目標地址,使其指向第4個字符。

代表MOVSB #what它究竟做什麼?

執行ecx迭代,每次從一個[ds:esi]字節複製到[es:edi]並且由一個遞增兩個(假設方向標誌是明確的,它通常是)。

這樣,該代碼相當於:

for(i = 0; i < 6; i++) x[i + 3] = x[i]; 

的從字符串的開頭在自身開始當然拷貝6個字符這將通過3偏移然而,當i >= 3它將讀取的字節已經複製:

1. abcae 
2. abcab 
3. abcabc 
4. abcabca 
5. abcabcab 
6. abcabcabc 
2

英特爾的手冊鏈接從https://stackoverflow.com/tags/x86/info。你會發現movsb所做的一切的確切和詳細的描述。指針增量的方向取決於「方向」標誌,但常用的ABI需要在函數輸入時清除方向標誌(所以esi/edi遞增,不遞減)。除非你正在編寫一個引導程序(應該儘可能少地假設初始狀態),否則你可以假設DF被清除,除非你自己設置。

重疊源和目標將產生這樣的東西。讀取的第4個字節不是讀取d,而是作爲第一個字節寫入的aadd $3, %edi顯然將目的地設置爲x+3,我想要演示一個重疊的副本。更好的代碼本來是用一個lea 3(%esi), %edi insn代替mov/add對。

您確定abcabcabc是您在y發現的嗎?這正是你應該在x上找到的,後面的零字節是原來在y(不是movs複製的那個)中的零字節。


即使rep movs的微碼實現將使用64位加載/存儲的高性能,但它仍然處理緊密重疊的src和dest的特殊情況。 (在這種情況下,IDK的性能可能回落到較慢的版本,或者找出重複的模式和排序stos)。

+1

很好的捕獲目標是'x',而不是'y'。 – enhzflep

+0

結果是書上說的。我不確定這本書是對還是錯。 – Wiiiii

+1

這本書是錯誤的,'y'處的9個字節只是最後一個'abc'和6個零字節。 – Jester

2

所有x86指令都在Intel's manuals中描述,所以我建議您下載它們。

MOVSB的描述是:

A4 MOVSB  For legacy mode, Move byte from address 
        DS:(E)SI to ES:(E)DI. For 64-bit mode move 
        byte from address (R|E)SI to (R|E)DI. 

用下面的操作的僞代碼:

DEST ← SRC; 

IF (Byte move) 
    THEN IF DF = 0 
    THEN 
     (E)SI ← (E)SI + 1; 
     (E)DI ← (E)DI + 1; 
    ELSE 
     (E)SI ← (E)SI – 1; 
     (E)DI ← (E)DI – 1; 
    FI; 
... 

REP前綴只是意味着:

重複的字符串指令計數寄存器中指定的次數。

這種情況下的計數寄存器是ecx

+1

作爲唯一提及對方向標誌值的依賴的人,你的回答似乎有點不受歡迎。你的觀察非常重要,恕我直言。 – enhzflep

1

在調試器中運行它,看看!基本上,esi(source)和edi(dest)都指向.string變量。然後edi被設置爲指向字符串開始處的3個字符,也就是指向保存'd'的內存。 此時被執行6倍(在rep movsb的形式)

  • MOV 1個字節從[ESI]至[EDI]
  • 增量ESI
  • 增量EDI
以下

編輯:正如所指出的邁克爾 - ESI和EDI是否遞增或遞減依賴於方向標誌。如果(已經)被設置,寄存器遞減。 /編輯

所以,目的地是在在所有時間源的前3個字節。因此,在複製了3個字節後,源現在指向rep movsb指令開始之前dest的位置。

+0

作爲唯一提到在調試器中運行它的人,你的答案似乎有點不受歡迎。 :D爲了記錄,我還提到了方向標誌。 – Jester

+0

只要它6次,應該是abcabc而不是abcabcabc吧? – Wiiiii

+1

@Wiiiii - 不完全。您忘記說明目標是源前3個字節的事實。因此,你會得到前3個字節'abc',然後是另外6個'abcabc'。在調試器中運行這種類型的練習是非常有用的時間消耗。 – enhzflep