<<匯編語言>>---王爽 (實驗 8)分析一個奇怪的程序


簡介 :

分析下面的程序 , 在運行前思考 , 這個程序可以正常返回嗎 ?
運行后再思考 , 為什么是這種結果 ?
通過這個程序加深對相關內容的理解

assume cs:code
code segment
    mov ax, 4C00H
    int 21H
    start:
        mov ax, 0000H
        s:
            nop
            nop
            mov di, offset s
            mov si, offset s2
            mov ax, cs:[si]
            mov cs:[di], ax
        s0:
            jmp short s
        s1:
            mov ax, 0000H
            int 21H
            mov ax, 0000H
        s2:
            jmp short s1
            nop
code ends
end start

分析 :

程序的執行流程是這樣的 :

; 從 start 標號開始
1. mov ax, 0000H
2. nop
3. nop
4. mov di, offset s
5. mov si, offset s2
6. mov ax, cs:[si]
7. mov cs:[di], ax
8. jmp short s
9. jmp short si ; 這句 jmp short s1 , 根據我們之前的分析 , 指令是用相對偏移來表示的
; 因此執行的操作并不是真的跳轉到 s1 這個標號 , 而是跳轉編譯時確定的 該指令到 s1 標號的偏移
; 所以我們要分析接下來程序的流程的話 , 就必須先編譯程序 , 然后要知道到底偏移是多少
; 然后再根據這個偏移確定程序下一步應該執行哪里的指令
; 根據下圖的編譯結果 , 可以發現 , jmp short s1 在編譯后得到的指令是 : 
; 偏移是 : EB F6
; 這個數據是使用 補碼 來表示的 , 也就是說 , 是一個負數 , 然后符號位不變 , 其他位取反 , 然后加 1
; 然后 , 我們現在就知道了 , 這條指令是將 ip 的值加上 -10
; 我們再看看 ip - 10 指向的地址是哪里 ? 
; 對 , 剛好就是 code segment 開始的位置
10. mov ax, 4C00H
11. int 21H
; 這樣程序就實現了正常的返回

反編譯結果 :

注意這里使用 debug 的 u 命令進行反匯編的時候要指定代碼段的偏移地址為 0
否則 debug 會自動從 start 標號的地方開始反匯編
Paste_Image.png
可以看到 : 
jmp short s1 ; 這句匯編指令被翻譯成了 : EB F6 , 其中 EB 表示的是跳轉 , F6 表示偏移
F6 怎么理解呢 ? 
1111 0110 (使用補碼來表示)
補碼轉換成原碼 , 符號位不變 , 其他位取反 , 然后加 1
1000 1001
1000 1010 ; 也就是 -10
也就是上面我們分析的讓 (ip) = (ip) - 0x0A
然后 , 這句指令被復制到 s 標號的開頭處
由于 nop 只占一個字節 , 因此兩個 nop 被完全替代
然后程序執行到 s0 , 又跳轉到 s 開始的地方
這個時候就要執行 : (這個時候 ip = 8)
EB F6
首先讀取這條指令到指令緩存器里
接下來 , (ip) = (ip) + len(EB F6) = (ip) + 8 = 10
然后執行這條指令 , 即為 (ip) = (ip) - 10 = 0
這樣 ip 就回到了 code segment 的起始處
這樣繼續執行 
mov ax, 4C00H
int 21H
就實現了程序的正常返回
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容