1. 程式人生 > 其它 >實驗3 轉移指令跳轉原理及其簡單應用程式設計

實驗3 轉移指令跳轉原理及其簡單應用程式設計

實驗任務1

程式碼功能簡析

輸出兩行1 9 3
or 30h是為了轉換為\(ASCII\)碼輸出。 \(30h\) 是ASCII中 \('0'\) 的編號,其二進位制形式為:\(0011 0000\) ,所以or上一個 \(30h\) 表示輸出從'0'開始偏移量為1 9 3的數字
如果 or 61h ,則輸出的是偏移量減去 \(1\) 的小寫字母。( \(61h\)\(0110 0001\) ,從1開始)
$ 是預定義符號,表示當前的偏移地址,使用 jmp $ ,可以進入死迴圈。

問題1


反彙編檢視機器碼,可以看到其機器碼為 \(E2F2\)
\(E2\) 表示LOOP
\(F0\) 是補碼形式的位移量, \(F2\)

轉換為二進位制為 \(11110010\)
將其轉換為原碼 \(1!(1110010-1) = 1!(1110001) = 10001110 = -8+-4+-2=-14\)
所以其位移量為 \(-14\) 。當前ip為 \(0x19\) ,即 \(25\)\(25-14=11\)
但是s1處的偏移量為 \(D\) ,即 \(13\)
所以整個轉移的過程如下
ip指向 \(25\) 偏移處的指令,先取指令,然後ip自動 \(+2\) ,變為 \(27\) ,然後執行指令的過程中,將ip減去 \(14\) ,得到 \(13\) ,那麼下一條要執行的指令就在偏移量為 \(13\) 的地方,即s1標號處。

問題2

重複問題1的操作步驟。
\(F0\)

的二進位制形式為: \(11110000\)
得到其原碼: \(1!(1110000-1) = 1!(1101111) = 10010000 = -16\)
為什麼指令數量相同,但是位移量不同?原因出在incadd的指令佔位元組數不同。8086彙編採用動態指令長度,所以每條指令的長度都不是相同的。所以這裡會有位移量的不同。
CPU計算得到s2之後指令的地址方式和問題1一樣,這裡不重複描述。

實驗任務2

程式碼簡析

assume cs:code, ds:data
data segment
    dw 200h,0h,230h,0h
data ends

stack segment
    db 16 dup(0)
stack ends

code segment
start:
    mov ax,data
    mov ds,ax

    mov word ptr ds:[0],offset s1
    mov word ptr ds:[2],offset s2
    mov ds:[4],cs

    mov ax,stack
    mov ss,ax
    mov sp,16

    call word ptr ds:[0]
    ;push ip
    ;jmp word ptr ds:[0]
s1: pop ax
    ;(ax) = stack.top() = offset line23 + size(line23) = offset s1
    call dword ptr ds:[2]
    ;push cs
    ;push ip
    ;jmp dword ptr ds:[2]
s2: pop bx
    ;(bx) = stack.top() = offset line28 + size(line28) = offset s2
    pop cx
    ;(bx) = stack.top() = cs = code
    mov ah,4ch
    int 21h
code ends
end start

問題1

(ax) = offset s1
(bx) = offset s2
(cx) = cs = code

問題2

進入debug進行驗證。
驗證AX暫存器

驗證BX暫存器

驗證CX暫存器