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


四、實驗結論


 

1. 實驗任務1

此部分書寫內容:

  •  給出程序task1.asm源碼,及,運行截圖
 1 assume cs:code, ds:data
 2 
 3 data segment
 4     x db 1, 9, 3
 5     len1 equ $ - x
 6 
 7     y dw 1, 9, 3
 8     len2 equ $ - y
 9 data ends
10 
11 code segment
12 start:
13     mov ax, data
14     mov ds, ax
15 
16     mov si, offset x
17     mov cx, len1
18     mov ah, 2
19  s1:mov dl, [si]
20     or dl, 30h
21     int 21h
22 
23     mov dl, ' '
24     int 21h
25 
26     inc si
27     loop s1
28 
29     mov ah, 2
30     mov dl, 0ah
31     int 21h
32 
33     mov si, offset y
34     mov cx, len2/2
35     mov ah, 2
36  s2:mov dx, [si]
37     or dl, 30h
38     int 21h
39 
40     mov dl, ' '
41     int 21h
42 
43     add si, 2
44     loop s2
45 
46     mov ah, 4ch
47     int 21h
48 code ends
49 end start

  • 回答問題

① line27, 匯編指令 loop s1 跳轉時,是根據位移量跳轉的。通過debug反匯編,查看其機器碼,分析其跳轉的位移量是多少?(位移量數值以十進制數值回答)從CPU的角度,說明是如何計算得到跳轉后標號s1其后指令的偏移地址的。

 

0Dh-1Bh=F2h 換算成十進制為-14,即跳轉位移量是-14

CPU的角度,loop指令后,

跳轉地址=loop指令后第一個字節的地址+(“標號”處的地址-loop指令后的第一個字節的地址 )

簡單計算即:跳轉地址=1Bh+(0Dh-1Bh)=0Dh

在計算機內,偏移量是用八位二進制補碼表示,而補碼的減法又要轉換成加法來計算,實際計算過程如下:

1.首先算出8位偏移量——“標號”處的地址-loop指令后的第一個字節的地址

0000 1101(0D二進制補碼形式)

0001 1011(1B二進制補碼形式)

1110 0101(-1B的二進制補碼形式)

0000 1101-0001 1011=0000 1101+1110 0101=1111 0010(F2的二進制補碼形式)

計算機內,機器碼用補碼表示,可以看到機器碼E2F2,F2則是表示計算出的偏移量,換算成十進制-14。

2.算出偏移量后和loop指令后第一個字節首地址相加:

0001 1011+1111 0010=0000 1101(0D的二進制補碼形式)

  • 回答問題

② line44,匯編指令 loop s2 跳轉時,是根據位移量跳轉的。通過debug反匯編,查看其機器碼,分析其跳轉的位移量是多少?(位移量數值以十進制數值回答)從CPU的角度,說明是如何計算得到跳轉后標號s2其后指令的偏移地址的。

 

如問題①所示,偏移量=29h-39h=f0h 換算成十進制-16

CPU角度不再贅述。

2. 實驗任務2


 

此部分書寫內容:

  • 給出程序task2.asm源碼
     1 assume cs:code, ds:data
     2 
     3 data segment
     4     dw 200h, 0h, 230h, 0h
     5 data ends
     6 
     7 stack segment
     8     db 16 dup(0)
     9 stack ends
    10 
    11 code segment
    12 start:  
    13     mov ax, data
    14     mov ds, ax
    15 
    16     mov word ptr ds:[0], offset s1
    17     mov word ptr ds:[2], offset s2
    18     mov ds:[4], cs
    19 
    20     mov ax, stack
    21     mov ss, ax
    22     mov sp, 16
    23 
    24     call word ptr ds:[0]
    25 s1: pop ax
    26 
    27     call dword ptr ds:[2]
    28 s2: pop bx
    29     pop cx
    30 
    31     mov ah, 4ch
    32     int 21h
    33 code ends
    34 end start
  •  給出分析、調試、驗證后,寄存器(ax) = ? (bx) = ? (cx) = ? 附上調試結果界面截圖。

 

(ax)=0021 (bx)=0026 (cx)=076C

① 根據call指令的跳轉原理,先從理論上分析,程序執行到退出(line31)之前,寄存器(ax) =? 寄存器(bx) = ? 寄存器(cx) = ?

line 13-14 將數據段首地址賦值到ds寄存器

line 16-18 取標號s1的IP存入ds[0]地址,

取標號s2的IP存入下一個字節首地址即ds[2]地址,

cs段首地址存入下一個字節首地址即ds[4]

line 20-23 將棧段首地址賦值給ss寄存器並且將棧段指針指向棧頂

line 24 將下一條語句IP進棧,並且轉移到ds[0]所指向地址,由前文可知是s1標號地址進棧

line 25 將當前棧頂指針指向數據賦值給bx,由上文可知是s1標號IP地址

line 27 程序繼續向下執行,將下一條語句IP進棧,然后CS進棧,程序跳轉到ds[2]所指向地址即s2標號地址

line 28 將當前棧頂指針指向數據賦值給bx,即當前地址CS值

line 28 將當前棧頂指針指向數據賦值給cx,即當前地址IP值

② 對源程序進行匯編、鏈接,得到可執行程序task2.exe。使用debug調試,觀察、驗證調試

結果與理論分析結果是否一致。

 

對源程序反匯編可以看到,在line16處標號s1地址是0021,與下文s1標號出位置相符。line17同理。

程序執行前,棧內預存16個字節均為0

 

單步執行到line25,棧內數據為:

 

可以看到0021進棧,同時也因為單步執行保護現場,將下一條命令的CSIP值也存入棧。

繼續執行到line 27,棧內數據為:

 

可以看到下一條指令的IPCS值進棧。

程序繼續執行到line29,可以看到結果如下:

 

與理論分析結果一致。

3. 實驗任務3


 

此部分書寫內容:

  • 給出程序源碼task3.asm
     1 assume cs:code, ds:data
     2 data segment
     3     x db 99, 72, 85, 63, 89, 97, 55 
     4     len equ $- x 
     5 data ends
     6 
     7 code segment
     8 start:    
     9     mov ax, data
    10     mov ds, ax
    11     mov si, offset x
    12     mov cx, len
    13     mov bl,10
    14  
    15  s1:mov ah,0
    16     mov al, [si]
    17     div bl
    18     or al,30h
    19     mov dh,al;存商
    20     or ah,30h
    21     mov bh,ah;存余數
    22    
    23     mov ah,2
    24     ;輸出商位
    25     mov dl,dh
    26     int 21h
    27     ;輸出余數位
    28     mov dl,bh
    29     int 21h
    30     ;輸出空格
    31     mov dl, ' '
    32     int 21h
    33     
    34     inc si
    35     loop s1
    36  
    37    mov ah,4ch
    38    int 21h
    39 code ends
    40 end start
  • 運行測試截圖

 

4. 實驗任務4


 

此部分書寫內容:

  • 給出程序源碼task4.asm
     1 assume cs:code,ds:data
     2 
     3 data segment
     4     str db 'try'
     5     len equ $-str
     6 data ends
     7 
     8 code segment
     9 start:
    10     mov ax,data
    11     mov ds,ax
    12     
    13     mov ax,0b800h
    14     mov es,ax
    15     mov bx,0h;第一行
    16 
    17     mov si,offset str
    18     mov cx,len
    19 s1: 
    20     mov dl,[si];低位存放字符Ascii碼
    21     mov es:[bx],dl
    22     mov dl,2h;設置屬性
    23     mov es:[bx+1],dl;屬性放入顯示地址 高位地址
    24     
    25     add bx,2
    26     inc si
    27     loop s1
    28 
    29     mov bx,0f00h;第25行
    30     mov cx,len
    31     mov si,offset str
    32 s2:
    33     mov dl,[si];低位存放字符Ascii碼
    34     mov es:[bx],dl
    35     mov dl,4h;設置屬性
    36     mov es:[bx+1],dl;屬性放入顯示地址 高位地址
    37     
    38     add bx,2
    39     inc si
    40     loop s2
    41 
    42 
    43     mov ah,4ch
    44     int 21h
    45 code ends
    46 end start
  • 運行測試截圖

 

5. 實驗任務5


 

此部分書寫內容:

  • 給出程序源碼task5.asm
     1 assume cs:code,ds:data
     2 
     3 data segment
     4     stu_no db '201983290480'
     5     len = $-stu_no
     6 data ends
     7 
     8 code segment
     9 start:
    10     mov ax,data
    11     mov ds,ax
    12 
    13     mov ax,0b800h
    14     mov es,ax
    15 
    16     mov bx,0
    17     mov cx,1920
    18     call s1
    19 
    20     mov bx,0f00h
    21 Tos2: mov cx,34
    22     call s2
    23 
    24     mov si,offset stu_no
    25     mov cx,len
    26     mov bx,0f44h
    27     call s3
    28 
    29     mov ah,4ch
    30     int 21h
    31  
    32  s1: 
    33     mov dl,' '
    34     mov es:[bx],dl
    35     mov dl,1fh
    36     mov es:[bx+1],dl
    37     add bx,2
    38     loop s1
    39     ret
    40   
    41 s2: 
    42     mov dl,'-'
    43     mov es:[bx],dl
    44     mov dl,1fh
    45     mov es:[bx+1],dl
    46     add bx,2
    47     loop s2
    48     ret
    49 
    50 s3: 
    51     mov dl,[si]
    52     mov es:[bx],dl
    53     mov dl,1fh
    54     mov es:[bx+1],dl
    55     add bx,2
    56     inc si
    57     cmp cx,1;如果=1,跳轉
    58     je Tos2
    59     loop s3
    60     ret 
    61 
    62 code ends
    63 end start
  • 運行測試截圖

 

五、實驗總結 

知識點歸納:

1.EQU 偽指令把一個符號名稱與一個整數表達式或一個任意文本連接起來,它有 3 種格式:

name EQU expression
name EQU symbol
name EQU <text>

第一種格式中,expression 必須是一個有效整數表達式。第二種格式中,symbol 是一個已存在的符號名稱,已經用 = 或 EQU 定義過了。第三種格式中,任何文本都可以岀現在<...>內。當匯編器在程序后面遇到 name 時,它就用整數值或文本來代替符號。

= 偽指令不同,在同一源代碼文件中,用 EQU 定義的符號不能被重新定義。這個限制可以防止現有符號在無意中被賦予新值。

2.$

“$” 是匯編語言中的一個預定義符號,等價於當前正匯編到的段的當前偏移值。例如eg:指令“jmp $+3”中的“$”表示當前這條指令在代碼段中的偏移量

eg即“jmp $+3”表示要向前跳轉到距離這條指令3個字節的地方。若是“jmp $-3”,則表示要向后跳轉到距離這條指令3個字節的地方。

在匯編中是字符串結束的標志

如:DATA SEGMENT

MES1 'HELLO',0AH,0DH,'$'


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM