<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Switernal's Blogs

      看見每一種可能。

      博客園 首頁 新隨筆 聯系 訂閱 管理

      匯編實驗4 8086標志寄存器及中斷

      實驗任務1

      源代碼

      功能:對128位的兩個數字進行求和運算

      點擊查看代碼
      assume cs:code, ds:data
      
      data segment
         x dw 1020h, 2240h, 9522h, 5060h, 3359h, 6652h, 2530h, 7031h
         y dw 3210h, 5510h, 6066h, 5121h, 8801h, 6210h, 7119h, 3912h
      data ends
      code segment 
      start:
          mov ax, data
          mov ds, ax
          mov si, offset x    ; x -> si
          mov di, offset y    ; y -> di
          call add128
      
          mov ah, 4ch
          int 21h
      
      add128:
          push ax         ; 依次保存寄存器的值
          push cx
          push si
          push di
          
          sub ax, ax  ; 主要是把CF(進位)標志位置NC(0),否則第一次adc會出問題
          
          ; 由于8086是小端模式,根據邏輯來說,高高低低
          ; 左邊是低地址,應該是低位
          ; 從左加到右, 正好是從低位加到高位
          mov cx, 8       ; 8組數字
      s:  mov ax, [si]    ; x中的數
          adc ax, [di]    ; 帶進位的加法,加y中的數
          mov [si], ax    ; 結果送回x
      
          inc si  ; 如果換成add, 會影響CF的值,
          inc si  ; 本來應該有進位的, 如果用了add會導致CF = 0,
          inc di  ; 進位就失效了,
          inc di  ; 所以這里si和di只能用inc而不能用add.
          loop s
          
          pop di
          pop si
          pop cx
          pop ax
          ret
      code ends
      end start
      

      實驗問題解答

      line34~line37的4條inc指令,能否替換成如下代碼?

      add si,2
      add di,2
      

      答案:

      這段代碼data段給的數據可以,但是如果換成其它數據就不一定可以

      原因:

      這題中給的128位數據,每個16位相加都恰好都沒有產生進位,所以使用add即便修改了進位寄存器CF的值,也沒有影響。在這題中是可以替換的。

      但如果換成其他數據,若相加過程中產生了進位,則使用add會導致進位寄存器CF的值發生變化。

      如果本來應當是有進位的,CF的值為CY(1),但是做了add操作后CF會變成NC(0),會對后面的位數加法產生影響。所以不能使用add

      inc指令并不影標志寄存器CF的值。

      事實上,根據 intel 白皮書中對inc的描述,可以很清楚的知道這一點(Intel? 64 and IA-32 Architectures Software Developer’s Manual,Vol. 2A3-493):

      (翻譯:給目標操作數加1,同時保留CF標志的狀態。目標操作數可以是一個寄存器或一個內存位置。這條指令允許在不影響CF標志的情況下更新一個循環計數器。(使用即時操作數為1的ADD指令來執行更新CF標志的增量操作)。)

      ② 在debug中調試,觀察數據段中做128位加之前,和,加之后,數據段的值的變化。

      可以觀察到數據被正確求和了。

      觀察

      ① add指令對標志寄存器中的零標志位ZF(Zero Flag)、進位標志位CF(Carry Flag)是否有影響?

      答案:有影響

      根據 Intel 白皮書(Vol. 2A 3-31)對ADD指令的描述:

      (翻譯:ADD指令執行整數加法。它對有符號和無符號整數操作的結果進行評估,并設置OF和CF標志,分別表示有符號或無符號結果中的進位(溢出)。SF標志表示有符號結果的符號。)

      ② inc指令對標志寄存器中的零標志位ZF(Zero Flag)、進位標志位CF(Carry Flag)是否有影響?

      答案:對ZF有影響,而對CF無影響

      根據 intel 白皮書中對inc的描述,可以很清楚的知道這一點(Intel? 64 and IA-32 Architectures Software Developer’s Manual,Vol. 2A3-493):

      實驗任務2

      源代碼

      點擊查看代碼
      assume cs:code, ds:data
      data segment
              str db 80 dup(?)
      data ends
      
      code segment
      start:  
              mov ax, data
              mov ds, ax
              mov si, 0
      s1:        
              mov ah, 1       ; 調用int 21h的1號子程序
              int 21h         ; 從鍵盤接收輸入
              mov [si], al    ; 把輸入的字符放入 ds:[si]
              cmp al, '#'     ; 判斷接收到的字符是否是# 
              je next         ; 如果是'#',執行next處操作
              inc si          ; 否則si + 1
              jmp s1          ; 返回s1繼續讀入下一個字符
      next:
              mov ah, 2       ; 調用
              mov dl, 0ah     ; 0ah是換行符回車的ASCII碼
              int 21h         ; 打印一個換行符
              
              mov cx, si      ; 由于si從0開始,si = 讀入的字符個數-1,正好不會把'#'打印出來
              mov si, 0       ; si回到字符串開始的位置
      s2:     mov ah, 2       ; 調用2號子程序
              mov dl, [si]    ; 打印字符
              int 21h         
              inc si                  
              loop s2         ; 打印字符串循環
      
              mov ah, 4ch     
              int 21h
      code ends
      end start
      

      實驗結果

      實驗分析

      該程序的作用是:從鍵盤接收輸入一串以#為結尾的字符串,然后將其打印在屏幕上

      ① 匯編指令代碼line11-18,實現的功能是?

      s1:        
              mov ah, 1       ; 調用int 21h的1號子程序
              int 21h         ; 從鍵盤接收輸入
              mov [si], al    ; 把輸入的字符放入 ds:[si]
              cmp al, '#'     ; 判斷接收到的字符是否是# 
              je next         ; 如果是'#',執行next處操作
              inc si          ; 否則si + 1
              jmp s1          ; 返回s1繼續讀入下一個字符
      

      總結:從鍵盤上讀取輸入的字符,并保存到ds:[si],每讀入一個就判斷是否為#,如果是則不保存,轉跳至標號next處執行;如果不是則si + 1并繼續讀入下一個字符。

      ② 匯編指令代碼line20-22,實現的功能是?

        mov ah, 2       ; 調用
        mov dl, 0ah     ; 0ah是換行符回車的ASCII碼
        int 21h         ; 打印一個換行符
      

      總結:打印一個回車(換行符)

      ③ 匯編指令代碼line24-30,實現的功能是?

          mov cx, si      ; 由于si從0開始,si = 讀入的字符個數-1,正好不會把'#'打印出來
          mov si, 0       ; si回到字符串開始的位置
      s2: mov ah, 2       ; 調用int 21h的2號子程序
          mov dl, [si]    ; 打印字符
          int 21h         
          inc si                  
          loop s2         ; 打印字符串循環
      

      總結:打印字符串,并且不會把#打出來

      說明(實驗指導里給的)

      1. DOS系統功能調用int 21h的1號子功能:

      功能:從鍵盤上輸入單個字符

      入口參數:(ah) = 1

      出口參數: (al)存放輸入字符的ASCII碼

      即:

      mov ah,1
      int 21h ; (al) <-- 輸入字符的ascII碼
      
      1. DOS系統功能調用int 21h的2號子功能

      功能:輸出單個字符到屏幕上

      入口參數:(ah) = 2, (dl) = 待輸出的字符或其ascII碼

      出口參數:無

      即:

      mov ah, 2
      mov dl, ×× ; ××是待輸出的字符,或,其ascII碼 
      int 21h
      

      實驗任務3

      題目描述

      注:該任務是對實驗3的任務3進行改進。

      針對8086CPU,已知邏輯段定義如下:

      data segment
      		x dw 91, 792, 8536, 65521, 2021 
      		len equ $ - x
      data ends
      

      編寫8086匯編源程序task3.asm,在屏幕上以十進制形式輸出data段中這一組連續的數據,數據和數據之間以空格間隔。

      要求:

      • 編寫子程序printNumber

        • 功能:以十進制形式輸出一個任意位數的整數(整數范圍0 ~ 65535)
        • 入口參數:寄存器ax(待輸出的數據 --> ax)
        • 出口參數:無
      • 編寫子程序printSpace

        • 功能:打印一個空格
        • 入口參數:無
        • 出口參數:無
      • 在主體代碼中,綜合應用尋址方式和循環,調用printNumber和printSpace, 實現題目要求。

      源代碼

      點擊查看代碼
      ; 可以打印0~65535不定位數的數字
      assume ds:data, cs:code, ss:stack
      
      data segment
          x dw 91, 792, 8536, 65535, 2021, 0
          len equ $ - x
      data ends
      
      stack segment
          dw 8 dup(?)
      stack ends
      
      code segment
      start:
          mov ax, data
          mov ds, ax
      
          mov ax, stack
          mov ss, ax
          mov sp, 16
      
          mov cx, len/2 ; 由于數據都是word型,所以len/2才是數據個數
          ; print循環: 依次打印所有數字
          print:
              mov ax, word ptr ds:[di]    ; 把數據放入al
              add di, 2                   ; di指針后移2字節
      
              push cx             ; 把cx保存起來, 子程序中會修改cx值
      
              call printNumber    ; 打印數字
              call printSpace     ; 打印空格
      
              pop cx              ; 恢復cx
          loop print
          
          mov ah, 4ch
          int 21h
      
      ; 子程序: printNumber
      ; 功能: 打印數字
      ;   入口參數: 
      ;       寄存器ax  (待輸出的數據 --> ax)
      ;   局部變量說明: 
      ;       bx -> 存儲數字字符個數
      printNumber:
          mov bx, 0       ; 獲取之前位數為0
          ; 逐位獲取數字
          ; getEach循環: 獲取每一位,然后壓入棧中
          getEach:
              ; 除數放在16位寄存器bp中
              mov bp, 10      ; 除10運算
              mov dx, 0       ; 由于除數是16位寄存器,dx也是被除數一部分,需要置零      
              div bp          ; 數據除10
      
              push dx         ; 將數字壓入棧中(余數在dx里)
              inc bx          ; 位數+1
              
              mov cx, ax      ; 除法商賦給cx, 如果商為0則說明所有位數都獲取完了
              inc cx          ; 由于loop時會-1,這里先+1,防止出現負數
      
          loop getEach
      
          ; 打印數字
          mov cx, bx          ; 先把bx存的數字位數賦給cx
          ; printEach循環: 依次從棧中取出數字,逐位打印
          printEach:
              pop dx          ; 取出一位數
              add dl, 30h     ; dl是剛才除法的余數,也就是需要得到的位數,+30h是轉成對應字符
              mov ah, 2       ; 調用int 21h的2號子程序打印
              int 21h
          loop printEach 
      
          ret
      
      ; 子程序: printSpace
      ; 功能: 打印空格
      printSpace:
          mov ah, 2
          mov dl, 20h
          int 21h
          ret
      
      code ends
      end start
      

      實驗結果

      該程序可以成功打印0~65535之間的任意數字。

      實驗說明

      說明全部寫在注釋中。

      實驗任務4

      題目描述

      針對8086CPU,已知邏輯段定義如下:

      data segment
      		str db "assembly language, it's not difficult but tedious" 
      		len equ $ - str
      data ends
      

      編寫8086匯編源程序task4.asm,將data段中字符串里的小寫字符轉換成大寫。

      要求:

      • 編寫子程序strupr
        • 功能:將包含任意字符的字符串中的小寫字母變成大寫
        • 入口參數
          • (ds:si) 字符串首地址的段地址和偏移地址分別送至ds和si
          • (cx) 字符串的長度
        • 出口參數:無
      • 在主體代碼中,設置入口參數,調用strupr, 實現題目要求。

      源代碼

      點擊查看代碼
      assume cs:code,ds:data
      data segment
          str db "assembly language, it's not difficult but tedious"
          len equ $ - str
      data ends
      
      stack segment
          db 8 dup(?)
      stack ends
      
      code segment
      start: 
          mov ax, data
          mov ds, ax
          mov si, 0
          mov cx, len     ; 參數:字符串長度存在cx中
          call strupr     ; 調用轉換子程序
          call printStr   ; 調用打印子程序
      
          mov ax, 4c00h
          int 21h
      
      ; 子程序 strupr
      ;   功能: 將包含任意字符的字符串中的小寫字母變成大寫
      ;   入口參數
      ;       (ds:si) 字符串首地址的段地址和偏移地址分別送至ds和si
      ;       (cx) 字符串的長度 
      strupr:
          push cx
          push si         ; 先保存兩個寄存器的值
          transform:
              mov al, ds:[si] ; 取出一個字符
              cmp al, 97      ; 判斷ASCII碼是否 >= 97
              jl continue     ; 小于97直接進入下次循環
              cmp al, 122     ; 判斷ASCII碼是否 <= 122
              jg continue     ; 大于122直接進入下次循環
              and al, 0dfh    ; 小寫轉成大寫,原理詳見實驗2
              mov ds:[si], al ; 把轉換后的字符送回data段
          continue:
              inc si          ; 指針后移
              loop transform  ; 循環
      
          pop si
          pop cx          ; 恢復寄存器的值
          ret             ; 返回
      
      ; 子程序 printStr
      ;   功能: 打印字符串
      ;   入口參數
      ;       (ds:si) 字符串首地址的段地址和偏移地址分別送至ds和si
      ;       (cx) 字符串的長度
      printStr:
          push cx         ; 保存寄存器的值
          push si
      
          print:          ; 打印字符循環
              mov ah, 2
              mov dl, ds:[si]
              int 21h
              inc si
          loop print
      
          pop si          ; 恢復寄存器的值
          pop cx
          ret             ; 返回
      
      code ends
      end start
      

      實驗結果

      可以看到,該程序成功將小寫字母轉成了大寫。

      實驗任務5

      源代碼

      點擊查看代碼
      assume cs:code, ds:data
      
      data segment
          str1 db "yes", '$'
          str2 db "no", '$'
      data ends
      
      code segment
      start:
          mov ax, data
          mov ds, ax
      
          mov ah, 1   ; 調用int 21h的1號子程序進行單字符輸入
          int 21h
      
          mov ah, 2       ; 調用BIOS中斷例程int 10h的2號子功能
          mov bh, 0       ; 設置顯示頁為第0頁
          mov dh, 24      ; 設置光標位置在第24行
          mov dl, 70      ; 設置光標位置在第70列
          int 10h         ; 設置光標位置
      
          cmp al, '7'     ; 把輸入的字符和字符'7'進行比較
          je s1           ; 如果輸入的字符是'7',就跳轉s1處
          mov ah, 9       ; 調用int 21h的9號子程序顯示str2
          mov dx, offset str2 ; 把標號str2的偏移量放入dx
          int 21h             ; 顯示標號str2處的字符串(no)
      
          jmp over            ; 無條件跳轉到over處
      
      s1: mov ah, 9           ; 調用int 21h的9號子程序顯示str1
          mov dx, offset str1 
          int 21h             ; 顯示標號str1處的字符串(yes)
      over:  
          mov ah, 4ch         ; 程序結束
          int 21h
      code ends
      end start
      

      運行結果

      輸入7后,屏幕上倒數第2行右下角顯示yes

      輸入其它字符,屏幕上倒數第2行右下角顯示no

      總結和理解

      該程序的解釋已經全部寫在源代碼的注釋中。

      總結一下,這個程序實現的功能是:

      從鍵盤輸入一個字符,判斷輸入的字符是否為7

      如果為7,則從屏幕的第24行第70列開始顯示yes

      如果不為7,則從屏幕的第24行第70列開始顯示no

      實驗任務6

      運行42號中斷程序

      通過編譯連接運行task6_1.asmtask6_2.asm后可以看到,屏幕底部出現了綠色的"welcome to 2049!",說明42號中斷程序被成功調用。

      自定義中斷:36號中斷程序

      源代碼

      點擊查看代碼
      assume cs:code
      code segment
      start:
          ; 36號中斷
          mov ax, cs
          mov ds, ax
          mov si, offset int36   ; set ds:si
      
          mov ax, 0
          mov es, ax
          mov di, 200h        ; set es:di
      
          ; 復制中斷程序到 es:[di]
          mov cx, offset int36_end - offset int36
          cld
          rep movsb
      
          ; 設置中斷向量表
          mov ax, 0
          mov es, ax
          mov word ptr es:[36*4], 200h
          mov word ptr es:[36*4+2], 0
      
          ; 調用36號中斷程序
          int 36
      
          ; 程序結束
          mov ah, 4ch
          int 21h
      
      ; 36號中斷程序
      int36: 
          jmp short int36_start
          stu_num db "201983290048 Li Qingyun"
          len1 equ $ - stu_num
          task db "Assembly Experiment 4 Interrupt No.36"
          len2 equ $ - task
      
          ; 中斷程序指令部分
      int36_start:
          mov ax, cs
          mov ds, ax
          mov di, 202h
      
          call printString
          iret
      
      ; 打印子程序:
      ;   參數說明:
      ;       學號字符串存儲在 -> ds:[di]
      printString:
          mov ax, 0b800h
          mov es, ax      ; 控制顯存區域段指針
          mov si, 0       ; 顯存區域列指針從0開始
      
      ; 先把屏幕前11行置位藍色(第一行會被吃掉)
          mov al, 11      ; 全25行
          mov dl, 80     ; 每行160個字節文字和顏色都需要修改
          mul dl          ; 25*160, 獲得需要修改的字節數
      
          mov cx, ax      
          printBlue1:
              mov byte ptr es:[si], 20h    ; 用一個空格填充文字位置
              inc si              ; 后移指針
              mov byte ptr es:[si], 17h    ; 填充顏色: 藍底+白字:0 001 0 111 -> 17h
              inc si              ; 后移指針
          loop printBlue1
      
      ; 把屏幕中間5行置為白底藍字
          mov cx, 5*80      
          printWhite:
              mov byte ptr es:[si], 20h    ; 用一個空格填充文字位置
              inc si              ; 后移指針
              mov byte ptr es:[si], 71h    ; 填充顏色: 白底+藍字:0 111 0 001 -> 71h
              inc si              ; 后移指針
          loop printWhite
      
      ; 把屏幕最后10行置為藍色
          mov cx, 10*80      
          printBlue2:
              mov byte ptr es:[si], 20h    ; 用一個空格填充文字位置
              inc si              				 ; 后移指針
              mov byte ptr es:[si], 17h    ; 填充顏色: 藍底+白字:0 001 0 111 -> 17h
              inc si              ; 后移指針
          loop printBlue2
      
      
      ; 打印學號  
          mov si, 12*160        ; 從第12行開始打印
          mov dx, (80-len1)/2   ; 計算左右兩邊空格數    
          
          ; 調用打印空格的子程序, 打印學號左側的空格
          mov cx, dx
          call printSpace 
      
          ; 打印學號字符串
          mov cx, len1
          printNumber:
              mov al, ds:[di]		        ; 低位是字符
              mov ah, 71h				    		; 高位是顏色
              mov word ptr es:[si], ax	; 按字放入
              inc di
              add si, 2
          loop printNumber
      
          ; 再次調用打印空格的子程序, 打印學號右側的空格
          mov cx, dx
          call printSpace
      
      ; 打印下面一行文字
          mov si, 14*160          ; 從第14行開始打印
          mov dx, (80-len2)/2     ; 計算左右兩邊空格數 
          
          ; 調用打印空格的子程序, 打印文字左側的空格
          mov cx, dx
          call printSpace 
      
          ; 打印文字字符串
          mov cx, len2
          printTask:
              mov al, ds:[di]		        ; 低位是字符
              mov ah, 71h				    		; 高位是顏色
              mov word ptr es:[si], ax	; 按字放入
              inc di
              add si, 2
          loop printTask
      
          ; 再次調用打印空格的子程序, 打印文字右側的空格
          mov cx, dx
          call printSpace
      
          ret
      
      ; 子程序: 打印分隔符空格
      ;   參數: 長度 -> cx
      ;        位置 -> es:[si]
      printSpace:
          mov al, 20h        ; 一個空格    
          mov ah, 71h
          mov word ptr es:[si], ax
          add si, 2
          loop printSpace
          ret
      
      
      int36_end:
          nop
      
      
      code ends
      end start
      

      運行結果

      36號中斷的運行效果是:

      將屏幕背景變為藍色,中間5行背景變為白色;

      并居中打印"201983290048 Li Qingyun"和"Assembly Experiment 4 Interrupt No.36",表明這是36號中斷程序。

      所有說明都寫在代碼注釋中。

      總結與思考

      1. 標志寄存器會被多數指令修改,如addsubjmp等,而一些指令執行時也會使用標志寄存器的值來確定執行的方式,這可能會對操作結果造成影響。比如實驗一中,inc不會對CF造成影響,但add卻會,如果使用add再使用adc會對結果造成影響。
      2. movsbmovsw指令會使用方向寄存器的值,確定指針移動方向。
      3. cmp指令會對兩個操作數做減法,然后將結果存在標志寄存器中,有條件跳轉指令則會根據標志寄存器的值進行判斷并跳轉。
      4. 使用pushfpopf可以間接實現對標志寄存器的修改,但通常不需要這樣操作。
      5. 內中斷程序可以使CPU在執行到特殊情況時調用,中斷處理程序可以讓CPU從錯誤中恢復,比如除法中除0的錯誤。
      6. 中斷向量表存儲在0000:0000開始空間中,可以存一個字的中斷程序地址。
      posted on 2021-12-07 12:08  Switernal  閱讀(430)  評論(4)    收藏  舉報
      主站蜘蛛池模板: 精品国产亚洲av麻豆特色| 国产色视频一区二区三区| 97成人碰碰久久人人超级碰oo| 成人精品视频一区二区三区尤物| 威信县| 久久亚洲国产精品久久| 99久热在线精品视频| 中文字幕国产精品专区| 欧美视频网站www色| 成人av天堂男人资源站| 久久精品一区二区三区综合| 国产性三级高清在线观看| 国产福利酱国产一区二区| 女同性恋一区二区三区视频| 精品国产午夜福利伦理片| 亚洲国产亚洲综合在线尤物| 亚洲日韩性欧美中文字幕| 免费人成视频网站在线观看18| 欧美白人最猛性xxxxx| 中文字幕亚洲人妻一区| 久青草视频在线免费观看| 日本熟妇乱一区二区三区| 国产综合色在线精品| 亚洲综合一区二区三区| 国产精品高清一区二区三区| 亚洲线精品一区二区三八戒| 欧美成本人视频免费播放| 男女性高爱潮免费网站| 军人粗大的内捧猛烈进出视频| 国产拍拍拍无码视频免费 | av天堂亚洲天堂亚洲天堂| 亚洲精品天堂在线观看| 玩弄放荡人妻少妇系列| 国产福利精品一区二区| 亚洲AV毛片一区二区三区| 久久亚洲精品情侣| 99精品国产在热久久婷婷| 亚洲av在线观看| 国产精品欧美福利久久| 一区二区三区在线 | 欧洲| 猫咪社区免费资源在线观看|