日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

寄存器(内存访问)---汇编学习笔记

發布時間:2025/3/15 编程问答 12 豆豆
生活随笔 收集整理的這篇文章主要介紹了 寄存器(内存访问)---汇编学习笔记 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

寄存器(內存訪問)


序言

第二章,我們主要從CPU如何執行指令的角度講解了8086CPU的邏輯結構、形成物理地址的方法、相關的寄存器以及一些指令。

這一章,我們從訪問內存的角度繼續學習幾個寄存器。


3.1 內存中字的存儲

CPU中,用16位寄存器來存儲一個字。字是有2個內存單元組成。高8位存放高位字節,低8位存放低位字節

例如:問題 3.1 所描述的。

(1) 0 地址單元中存放的字節型數據是多少?
(2) 0 地址字單元中存放的字型數據是多少?
(3) 2 地址單元中存放的字節型數據是多少?
(4) 2 地址字單元中存放的字型數據是多少?
(5) 1 地址字單元中存放的字型數據是多少?

答案一目了然,分別是20H、4E20H、12H、0012H、124E。


3.2 DS和[address]

CPU要讀寫一個內存單元時,必須給出這個內存單元的地址,內存地址由段地址和偏移地址組成。 DS 存放要訪問數據的段地址[address] 中address是偏移地址并且是一個具體的數

這里注意,DS并不能直接給定一個數值。比如 mov ds,1000H 語句在8086CPU中是錯的。我們只能通過寄存器去改變ds的值,比如 mov ds,ax 語句。

問題 3.2

寫幾條指令,將 al 中的數據送入內存單元 10000H 中。

mov ax,1000H ;為了讓ds為1000H,先讓ax為1000H mov ds,ax ;ds只接受寄存器向它傳送的數據 mov al,[0] ;[0]是偏移地址,1000:0的內存單元是10000H

3.3 字的傳送

8086CPU是 16 位結構,有16根數據線,所以,可以一次性傳送16位數據,也就是一個字。

問題 3.3

內存中的情況如下圖所示,寫出下面指令執行后寄存器ax,bx,cx中的值。

mov ax,1000H ;AX = 1000H mov ds,ax ;DS = 1000H mov ax,[0] ;由于傳送的是一個字數據,所以AX = 1123H mov bx,[2] ;同上,BX = 6622H mov cx,[1] ;CX = 2211H add bx,[1] ;BX = 8833H add cx,[2] ;CX = 8833H

問題 3.4

內存中的情況如圖所示,寫出下面指令執行后內存中的值。

mov ax,1000H ;AX = 1000H mov ds,ax ;DS = 1000H mov ax,11316 ;AX = 11316 = 0x2C34H mov [0],ax ;1000:0 = 34 , 1000:1 = 2C mov bx,[0] ;BX = 2C34 sub bx,[2] ;BX = 1B12 mov [2],bx ;1000:2 = 12 , 1000:3 = 1B

我們知道高字節放入高地址,低字節放入低地址。也就是[0]的高地址為1000:1,低地址為1000:0。


3.4 mov、add、sub指令

我們在沒什么了解的情況之前就是是要幾個了mov、add、sub等指令。

先了解mov指令的幾種形式:

mov 寄存器,數據 mov 寄存器,寄存器 mov 寄存器,內存單元 mov 內存單元,寄存器 mov 段寄存器,寄存器

(1)我們猜想,既然有 mov 段寄存器,寄存器 指令,那么會有mov 寄存器,段寄存器 指令這樣的相反通路嗎?

實驗如下(再此聲明一次:借用了實驗樓的環境):

如圖所示:

  • 第一個紅框的 AX 為 0000H;
  • 第二個紅框是 DS 為 1000H;
  • 第三個紅框發生AX的值改變。

由此可知,mov 寄存器,段寄存器指令是可用的

(2)同樣,既然有 mov 寄存器,內存單元 ,會擁有 mov 內存單元,寄存器 指令嗎?

實驗如下:

如圖所示,內存單元 1000:0 和 1000:1 發生變化,也就是1000:[0]發生變化。

(3)那么 mov 段寄存器,內存單元 也應該可以。

實驗如下:

發現指令出錯。

同mov一樣, add 和 sub 也有以下幾種形式:

add 寄存器,數據 add 寄存器,寄存器 add 寄存器,內存單元 add 內存單元,寄存器sub 寄存器,數據 sub 寄存器,寄存器 sub 寄存器,內存單元 sub 內存單元,寄存器

我們嘗試一下 add 段寄存器,ax 指令,看看可行嗎?

實驗如下:

指令出錯。


3.5 數據段

前面提到,可以根據需要,將一組內存單元定義為一個。我們可以將一組的長度為N(N<=64KB)、地址連續、起始地址為16的倍數的內存單元當作專門存儲數據的內存空間。

例如將 123B0H~123B9H 的內存單元定義為數據段。現在要累加這個數據段中的前3個單元中的數據,如下:

mov ax,123BH mov ds,ax mov al,0 ;注意,由于題目要求是"單元",而不是"字",所以采用al add al,[0] add al,[1] add al,[2]

問題 3.5

寫幾條指令,累加數據段中的前3個字型數據。代碼如下:

mov ax,123BH mov ds,ax mov ax,[0] ;因為這里采用的是"字" add ax,[2] add ax,[4]

3.1~3.5 小結

(1)字在內存中存儲時,采用兩個地址連續的內存單元來存放,字的低位字節存放在低地址單元中,高位字節存放在高地址單元中。

(2)用 mov 指令訪問內存單元,可以在 mov 指令中只給出單元的偏移地址,此時,段地址默認在 DS 寄存器中。

(3)[address] 表示一個偏移地址為 address 的內存單元。

(4)在內存和寄存器之間傳送字型數據時,高地址單元和高8位寄存器、低地址單元和低8位寄存器相對應。

(5)mov、add、sub 是具有兩個操作對象的指令。jmp 是具有一個操作對象的指令。

(6)可以根據自己的推測,在 Debug 中實驗指令的新格式。

其實,最麻煩的就是第6點,每種CPU的匯編指令都會有一些不同,所以在針對不同的CPU時需要去猜測所謂的“新格式”。


檢測點 3.1

(1)在 Debug 中,用“d 0:0 1f”查看內存,結果如下。

寫出下面每條匯編指令執行后寄存器的值。

mov ax,1 ;AX = 0001H mov ds,ax ;DS = 0001H mov ax,[0000] ;AX = 2662H mov bx,[0001] ;BX = E626H mov ax,bx ;AX = E626H mov ax,[0000] ;AX = 2662H mov bx,[0002] ;BX = D6E6H add ax,bx ;AX = FD48H add ax,[0004] ;AX = 2C14H mov ax,0 ;AX = 0000H mov al,[0002] ;AL = E6H mov bx,0 ;BX = 0000H mov bl,[000c] ;BL = 26H add al,bl ;AL = 0CH

(2)內存中的情況如圖 3.6 所示。

各寄存器的初始值:CS=2000H , IP=0 , DS=1000H , AX=0 , BX=0;

  • 寫出CPU執行的指令序列(用匯編指令寫出)。
  • 寫出CPU執行每條指令后,CS、IP和相關寄存器中的數值。
  • 再次體會:數據和程序有區別嗎?如何確定內存中的信息哪些是數據,哪些是程序?
  • ①:我們知道CS=2000H,IP=0,所以從2000:0000處開始執行。因此,代碼如下。

    mov ax,6622H jmp 0FF0:0100 ;0FF0:0100 == 1000:0 mov ax,2000H mov ds,ax mov ax,[0008] mov ax,[0002]

    ②:CS:IP的值如下。

    指令CSIPaxds
    mov ax,66222000H0003H6622H1000H
    jmp 0FF0:0100OFFOH0100H6622H1000H
    mov ax,2000H0FF0H0103H2000H1000H
    mov ds,ax0FF0H0105H2000H2000H
    mov ax,[0008]0FF0H0108HC389H2000H
    mov ax,[0002]OFFOH010BHEA66H2000H

    ③:初步猜測,我認為數據和指令無區別。原因,是因為可以將mov bx,ax當做數據傳送到[0008]內存中。那我們如何確定是數據還是指令呢?當然是通過我們的CS:IP來確認咯,IP指向的第一個值是我們的指令,例如A1是為 mov ax,內存地址 的指令。執行指令后,IP根據指令來確定向后移動幾個位置。(以上是本人的猜想,不知道是否成立)

    猜想:CP是時鐘脈沖,以A1為例子,我們知道讀取一個數據需要一個脈沖,A1是需要3個脈沖時間才能完成的操作?

    以上是本人猜想,未經過驗證。


    3.6 棧

    棧是一種具有特殊訪問方式的存儲空間。特殊點在于,數據入棧出棧的次序是“先進后出”或者說“后進先出”(LIFO,Last In First Out)。擁有兩種操作:入棧(PUSH)出棧(POP)


    3.7 CPU 提供的棧機制

    CPU 提供相關的指令來以棧的方式訪問內存空間。說明了,我們可以將一段內存當做棧來使用。(其實我們編程在寫遞歸的時候,總是很經常沒有考慮遞歸基的情況就運行程序,導致內存溢出。我們通過前面所說內存被當做棧來使用,推導出:其實就是棧內存被使用了無限次,導致的內存溢出結果。)

    如下所示是棧的操作:

    可以看出高地址單元存放高8位,低地址單元存放低8位。

    在這里,我們會疑惑!總結一下,大概是兩個問題。

  • CPU如何知道10000H~1000FH這段空間被當做棧來使用?
  • push和pop在執行的時候,如何知道哪個單元是棧頂單元?
  • 這里給出答案,8086CPU 中,有兩個寄存器SS、IP分別是棧的段地址和偏移地址。在任意時刻,SS:IP 指向棧頂元素。

    我們來看看PUSH操作的過程,如圖:

    反之,則是POP操作過程,如圖:

    我們看到,POP操作并沒有將棧頂之前的值 清 0 。

    問題 3.6

    如果將 10000H~1000FH 這段空間當做棧,初始狀態棧是空的,此時,SS=1000H,SP=?

    答案顯然是最高地址的下一個單元,即10010H。


    3.8 棧頂超界的問題

    我們知道棧頂的指向有 SS:IP 控制。但并沒有控制這??臻gpop次數過多導致下溢以及push多次導致上溢檢測。這樣會出現一個問題,我們腦海中的棧空間之外的數據會被棧的pop或者push操作給覆蓋,從而導致一系列的錯誤發生。這非常嚴重,試想一下,如果C語言編寫的一段遞歸程序沒有遞歸基就運行之后,秒級的時候就會講內存占滿,從而導致RAM死機,計算機只能重啟。這也是為什么VC++給程序只分配了4K空間的原因(我記得是4K,若有錯誤請指正)。

    因此,我們在編寫匯編程序的時候,需要注意我們的PUSH和POP操作不會導致上溢以及下溢。


    3.9 push、pop 指令

    push和pop 指令的格式可以是如下形式:

    push 寄存器 ;將一個寄存器中的數據入棧 pop 寄存器 ;出棧,用一個寄存器接受出棧的數據 push 段寄存器 pop 段寄存器 push 內存單元 pop 內存單元

    問題 3.7
    編程,將 10000H~1000FH 這段空間當做棧,初始狀態棧是空的,將 AX、BX、DS 中的數據入棧。

    mov ax,1000H mov ss,ax ;由于是段寄存器,所以需要ax來中轉 mov sp,0010H ;由于棧是由高地址開始 push ax push bx push ds

    問題 3.8

    編程:
    (1)將 10000H~1000FH 這段空間當作棧,初始狀態棧是空的;
    (2)設置 AX=001AH,BX=001BH;
    (3)將 AX、BX 中的數據入棧;
    (4)然后將AX、BX清零;
    (5)從棧中恢復AX、BX原來的內容。

    ;第一題答案 mov ax,1000H mov ss,ax mov sp,0010H;第二題答案 mov ax,001AH mov bx,001BH;第三題答案 push ax push bx;第四題答案 mov ax,0000H mov bx,0000H;第五題答案 pop bx ;出棧順序是LIFO pop ax ;同上

    問題 3.9
    編程:
    (1)將 10000H~1000FH 這段空間當做棧,初始狀態為空;
    (2)設置 AX=001AH,BX=001BH;
    (3)利用棧,交換 AX 和 BX 中的數據。

    ;第一題答案 mov ax,1000H mov ss,ax mov sp,0010H;第二題答案 mov ax,001AH mov bx,001BH;第三題答案 push ax push bx pop ax pop bx

    問題 3.10

    如果要在 10000H 處寫入字型數據 2266H,可以用以下代碼完成:

    mov ax,1000H mov ds,ax mov ax,2266H mov [0],ax

    補全下面的代碼,實現功能:在 10000H 處寫入字型數據 2266H 。
    要求:不能使用“mov 內存單元,寄存器”這類指令。

    ;要求三條指令搞定 mov ax,1000H mov ss,ax mov sp,2H ;push是先將sp-=2后再傳送數據給SS:SP內存單元中;題目的代碼 mov ax,2266H push ax

    棧的綜述

    (1)8086CPU 提供了棧操作機制,方案如下。

    • 在 SS、IP 中存放棧頂的段地址和偏移地址;
    • 提供入棧和出棧指令,它們根據 SS:SP 指示的地址,按照棧的方式訪問內存單元。

    (2)push 指令的執行步驟:

    • SP=SP-2;
    • 向SS:SP指向的字單元中送入數據。

    (3)pop 指令的執行步驟:

    • 從 SS:SP 指向的子單元中讀取數據;
    • SP=SP+2。

    (4)任意時刻,SS:SP 指向棧頂元素。
    (5)8086CPU 只記錄棧頂,??臻g的大小我們要自己管理。
    (6)用棧來暫存以后需要回復的寄存器的內容時,寄存器出棧的順序要和入棧的順序相反。
    (7)push、pop 實質上是一種內存傳送指令,注意它們的靈活應用。

    棧是一種非常重要的機制,一定要深入理解,靈活掌握。


    3.10 棧段

    在編程時,我們可以根據需要,將一組內存單元定義為一個段。我們要注意控制棧不會超界。

    問題 3.11

    如果將 10000H~1FFFFH 這段空間當作棧段,初始狀態棧是空的,此時,SS=1000H,SP=?

    答案很顯然,SP= FFFF+1 = 10000H = 0000H。這是一個64K大小的棧段。

    問題 3.12
    一個棧最大可以設為多少?為什么?

    最大可以設為64K,因為SP的范圍只能是 0000H~FFFFH 之間。


    段的綜述

    • 數據段,段地址放在DS中,偏移地址[address]。
    • 代碼段,段地址放在CS中,偏移地址IP。
    • 棧段,段地址放在SS中,偏移地址SP。

    例如一段代碼,假設CS=1000H,IP=0000H:

    mov ax,1000H mov ss,ax mov sp,0020H mov ax,cs mov ds,ax mov ax,[0] add ax,[2] mov bx,[4] add bx,[6] push ax push bx pop ax pop bx

    這段代碼給我們的信息是:在 10000H~1001FH這段內存中,既是代碼段,又是棧段和數據段。這樣的代碼可能會出現數據發生錯誤,盡量讓一段內存當做三者中的一種段。


    檢測點 3.2

    (1)補全下面的程序,使其可以將 10000H~1000FH 中的 8 個字,逆序復制到 20000H~2000FH 中。逆序復制的含義如下圖所示。

    ;題目代碼 mov ax,1000H mov ds,ax;三行代碼 mov ax,2000H mov ss,ax mov sp,0010H;題目代碼 push [0] push [2] push [4] push [6] push [8] push [A] push [C] push [E]

    (2)補全下面的代碼,使其可以將 10000H~1000FH 中的 8 個字,逆序復制到 20000H~2000FH 中。

    ;題目代碼 mov ax,2000H mov ds,ax;三行代碼 mov ax,1000H mov ss,ax mov sp,0000H;題目代碼 pop [E] pop [C] pop [A] pop [8] pop [6] pop [4] pop [2] pop [0]

    實驗 2 用機器指令和匯編指令編程


    1. 預備知識:Debug 的使用

    • D命令,查看內存數據。
    • E命令,修改內存數據。
    • A命令,輸入匯編指令。
    • U命令,查看匯編程序。

    2. 實驗任務

    (1)使用 Debug,將上面的程序段寫入內存,逐條執行,根據指令執行后的實際運行情況填空。

    mov ax,FFFF mov ds,ax mov ax,2200 mov ss,ax mov sp,0100;填空 mov ax,[0] ;我們不考慮AX與BX的值 add ax,[2] mov bx,[4] add bx,[6]push ax ;研究SP的變化,SP = 00FEH push bx ;SP = 00FCH pop ax ;SP = 00FEH pop bx ;SP = 0100Hpush [4] ;SP = 00FEH push [6] ;SP = 00FCH

    (2)仔細觀察下圖的實驗過程,然后分析:為什么 2000:0~2000:f 中的內容會發生改變?

    我們發現指令 mov ss,ax 被執行后,下一條指令是 mov ax,3123 也就是說 一次T指令對ss操作連同sp也執行了。這變相的說明ss和sp需要連續的改變,也就是mov ss,ax之后必須是mov sp,10。

    那我們從中尋找原因:如果ss執行后,不立馬執行sp會發生什么情況?

    百度了一下,回答是這樣的,我們的 T指令 是中斷指令,也就是 T指令 執行后需要把相關寄存器信息壓入棧中。那么,我們就知道了,SS之后必須跟SP,否則會出現錯誤。執行后還需要把 T指令 相關的東西壓入棧中,所以出現了一堆數據。比如:0B39 是 DS 的值等。

    總結

    以上是生活随笔為你收集整理的寄存器(内存访问)---汇编学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。