2017-06-20 65 views
-2

爲什麼我的彙編代碼跳過一行?它讓跳過線mov AX,A彙編代碼跳過一行?

org 100h 
count equ 2 
A DW 5 
B DW 6 
Y0 DW ? 
Y1 DW ?  
mov AX,A  
add AX,B 
sub AX,count 
mov Y0,AX 
mov BX,B 
neg BX 
add BX,count 
mov Y1,BX 
ret 
+4

你不想把數據放在代碼執行路徑中......將它們移動到代碼之後。 – Jester

回答

6

讓我們來看看代碼字節這些指令助記符將裝配到:

   org 100h 
       count equ 2 
05 00   A DW 5 
06 00   B DW 6 
00 00   Y0 DW ? 
00 00   Y1 DW ?  
A1 00 01  mov AX,A  ;NASM "mov ax, [A]" 
03 06 02 01 add AX,B  ;NASM "add ax, [B]" 
83 E8 02  sub AX,count 
... 

代碼的字節都在左邊;指令助記符(您送入彙編程序的部分)位於右側。所有看起來不錯,對吧?

好了,現在讓我們來看看,當我們聚集會發生什麼,然後拆解代碼:

05 00 06   add ax,0x600 
00 00    add [bx+si],al 
00 00    add [bx+si],al 
00 B8 00 01  add [bx+si+0x100],bh 
05 02 01   add ax,0x102 
83 E8 02   sub ax,byte +0x2 

稍候...發生了什麼事?字節(左邊)相同,但指令助記符完全不同!它們與你最初寫的不一樣!

是什麼發生了,數據聲明說是你的代碼的頂部是由彙編所有盡職盡責地翻譯成字節,但隨後的反彙編翻譯這些(數據)字節回到可執行代碼。它沒有意識到它們是數據,因此它試圖將它們解釋爲要執行的指令。這不僅導致了不正確的說明,而且還導致了一個frameshift mutation,弄亂了所有下游。

所以它實際上並沒有「跳過」指令mov ax, a。就計算機可以說,該指令甚至不在那裏。它正在執行您在第二個代碼塊中看到的指令。基本上,它正在執行廢話。記住:在彙編程序中,一切都只是字節!

解決方案應該很明顯:不要將數據聲明與可執行代碼混合在一起。做的最好的事情將是移動數據下降到底部,下面所有的可執行代碼,其中執行永遠不會得到:

org 100h 
count equ 2 

mov AX,A  
add AX,B 
sub AX,count 
mov Y0,AX 
mov BX,B 
neg BX 
add BX,count 
mov Y1,BX 
ret 

A DW 5 
B DW 6 
Y0 DW ? 
Y1 DW ? 

介紹空白有助於打破東西成一個邏輯塊,使得代碼更具可讀性。請注意,我已將ORG指令留在頂端,因爲它必須在那裏。我也沒有將EQU指令移到底部。可以離開那裏,因爲它只是定義了一個彙編時間常量。正如您從一開始就可以看到的,它不會被轉換爲生成的機器代碼中的任何字節。

如果你不想動無論出於何種原因的數據,那麼你就必須插入指令跳過去:

org 100h 
count equ 2 

jmp Begin 

A DW 5 
B DW 6 
Y0 DW ? 
Y1 DW ?  

Begin: 
    mov AX,A  
    add AX,B 
    sub AX,count 
    mov Y0,AX 
    mov BX,B 
    neg BX 
    add BX,count 
    mov Y1,BX 
    ret 
+0

偉大的描述性答案。非常好的工作。 –

+0

您爲'add AX,B'寫的代碼(05 02 01)是錯誤的!當你想要的是「ADD r16,r/m16」時,你已經使用了'ADD AX,imm16'的編碼。所以操作碼變爲03h,產生一個4字節的指令。 – Fifoernik

+1

這很奇怪,@Fifoernik。我不知道我怎麼能得到錯誤的編碼。我通過NASM運行了這個程序,編譯了一個16位的二進制文件,首先正確寫入然後寫入錯誤,然後每次拆解結果。 (換句話說,我並沒有把它做到頭頂!)我不確定爲什麼它會在指令中使用錯誤的編碼。隨意編輯答案並修復它。或者當我有機會時,我會盡量記得回來並重溫它。 –

0

的問題是,在你的代碼中有混合操作碼與數據定義。這是完全錯誤的,因爲您的彙編程序會假定這些數據定義是助記符,並且繞過代碼。要查看它只需下載一個十六進制編輯器並查看代碼的十六進制格式。然後找到一個反彙編程序,並嘗試反彙編十六進制格式的代碼。您將看到反彙編程序顯示的代碼將與您在代碼中輸入的代碼有更多不同。換句話說,行mov AX, A不會被跳過,而不會被認爲是另一個操作碼。