16位匯編語言第二講系統調用原理,以及各個寄存器詳解


   16位匯編語言第二講系統調用原理,以及各個寄存器詳解

昨天已將簡單的寫了一下匯編代碼,並且執行了第一個顯示到屏幕的helloworld

問題?

  helloworld怎么顯示出來了.

一丶顯卡,顯存的概念

1.顯示hello就要操作顯示器,這是非常原始的,那個時候的程序員,並沒有像現在的RGB(紅綠藍)這樣的三色真彩色,那個時候就是操作顯卡的,定義了一個標准

這個標准就是我們要往固定的地址寫入數據,就會顯示出來

具體流程

操作顯卡 -> 顯卡有自己的緩存 -> 把數據寫入到顯存中, - > 顯示數據 (顯示到屏幕上)

但是那個時候是沒有字的,所以就開始造字,那個時候就是把英文的26的英文字母做出來顏色都是一樣的

比如 我們造一個1,並且把它放到顯存中

0 0 1 0 0

0 0 1 0 0   把這個1看做是一個二維數組,把這塊數據放到顯存中就會顯示1了.

0 0 1 0 0 

二丶鋸齒的概念

我們發現,很多游戲中都有一個選項,叫做坑鋸齒

其實鋸齒是因為,以前做 1的時候,顏色就是黑白的 這樣的字就有一點點的齒痕.看着不舒服,所以后邊,就用三色,把和一個字相同顏色的都放在一起

這樣看的字就很平滑,很好看.

可以看出,我寫了一個 1字,放大后旁邊的像素有藍色的,紅色的黃色的等等,而以前的就是黑色一種,所以看着很難看.

三丶系統調用原理

比如我們想顯示一個字符串,直接 "hello"雙引號包含起來,給操作系統即可.就會顯示了.

那么原理是什么.

  第一講中,說了一個指令字典,里面有功能號 int 21代表我們要調用那一項,而硬件是提供了一個表格,調用的時候直接查表

這個表格是函數指針數組,直接調用即可.

例如

但是我們會想,操作系統會調用這第21項顯示數據,那么這個表可能是無限的大的嗎,而操作系統提供的api就要好幾萬個,怎么一個表夠用嗎

所以后面有了ah寄存器傳參,上面的圖可以改為

當然可能不用Switch這種低效率的語法,會做優化,但是原理就是這樣,硬件廠商只提供指令,就是說我cpu一定會調用int 21指定,找到數組中的第21項

而 這個表格則是操作系統提供的.

所以現在就知道,什么是 int 21,和為什么ah給9才能顯示字符串了吧.

四丶新的問題系統沒有啟動之前就會顯示字符串

我們有沒有發現,系統還沒有啟動之前,就會顯示一段字符串,這個字符串是通過主板的bios顯示的

bios是不依賴於系統的,優先於系統存在.

操作系統啟動之后也可以調用

在指令字典中 

 

 在中斷碼中會有說,調用int 多少,參數通過什么寄存器給.等等. 他和cpu的那種表是不一樣的,但是都存在於操作系統啟動之前.

五丶寄存器詳解

1.IP指令寄存器

IP寄存器,上一講說過,IP寄存器適合CS段寄存器一起使用的,IP是偏移(ip寄存器叫做指令寄存器) 他是表示通過cs段寄存器 + IP的偏移,來確定下一條指令執行的位置

比如我們有一段匯編代碼

下一條指令執行的執行的位置是0100 ip就等於0100,可以用p指令查看. 其實ip等於0100是代表ip的偏移是0100,用cs段寄存器 * 16 + ip的偏移,就等於實際物理地址(也就是下一條指定指令的位置)也就是 mov ax,1

p指令調試查看

第一次

第一指令位置的偏移是0103 也就是 mov bx,2會開始執行,下面一次類推(不懂段寄存器,下面細講)

2.Flag標志寄存器

標志寄存器的好的博客簡介連接  https://my.oschina.net/clownfish/blog/142328

上一講也說了flag標志寄存器釋放各種標志的, flag標志器是16位

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
        OF DF IF TF SF ZF   AF   PF   CF

通常標志器是9個,常用的有6個,不常用的有三個,說下不常用的吧 DF IF TF,其余就是常用的了

CF 進位標志( Carry Flag) :

當我們做加法運算的時候,比如兩數相加 結果是否進位了

進位的時候,標志就是1,否則標志就是0,如果是加法運算,那么標志位1代表進位,如果為減法,那么標志為借位

比如 3AH + 7CH = B6H (h在匯編中代表前邊的數字是16進制) 沒有進位CF = 0

AAH + 7CH = (1) 26H,最高位進位了,CF = 1

 

ZF 零標志(Zero Flag):

表示你運算的結果為0,則ZF = 1,如果不為零則ZF = 0

例子:  

  3AH + 7CH = B6H,結果不為零,ZF = 0

  84H + 7CH = (1) 00H,結果是0,因為進位了,那么CF = 1

SF 符號標志位(sign flag):

表示運算的結果,最高位為1,則SF為1,否則最高位不為1 SF = 0

3AH + 7CH = B6H,結果的最高位不為零,以為B看做二進制的則是 1 0 1 1 最高位是1所以 SF = 1

84H + 7CH = (1) 00H,結果是0,最高位是0

PF 奇偶標志位 (Parity Flag)

表示你運算的結果中,統計1出現的個數(二進制的統計)如果1的個數為零,或者偶數的時候,則PF = 1,奇數則是0

比如

3AH + 7CH = B6H, = 1011 0110 B(后綴B代表二進制的意思) 統計個數,出現了五個1則PF = 0;

 OF 溢出標志位(OverFlow Flag)

若運算結果有溢出(或者結果不正確)則OF = 1,否則OF = 1

比如

3AH + 7CH = B6H 產生了溢出, OF = 1

AAH + 7CH = (1) 26H,進位了,但是沒有溢出,OF = 0

1.溢出

  在8位表達的整數返回的時候 是+127 -> -128

  在16位表達的范圍內是: +32767~ -32768

  比如 3AH + 7CH = B6H,在八位范圍中 3A = 10進制的58 7C = 十進制的124 

  那么結果就是58 + 124 = 182,遠遠超過了128的范圍,所以產生了一出,並一方面

  B6H的結果變成補碼,其值就是-74,顯然結果也是不正確的

2.溢出和進位的不同

  溢出標志OF,和進位標志CF是不同的,

極為標志表示無符號數運算的記過是否超出范圍,其運算結果仍然正確

溢出標志表示有符號數的運算結果是否超出了范圍,運算的結果已經是不正確了.

3.如何運用溢出和進位

這個取決於程序員

當處理器對兩個操作數進行運算的時候,會按照無符號的數據求得結果(為什么是無符號,因為負數有補碼)

並且設置進位標志位CF,同事,根據是否超出有符號數的范圍設置一處標志OF,也就是說也會設置進位,也會設置溢出標志位,設置溢出標志位的原因是無符號數已經超過了范圍了.

利用那個標志取決於程序員自己決定

 4.溢出的原理判斷

簡而言之就是 正數加正數等於正數,但是此時結果的二進制最高位為1(1是負數的意思)那么計算機就認為產生了一出

AF 輔助進位標志(Auxiliary Carry Flag)

輔助標志位主要表示的是低4個的進位或者借位,和CF不同,CF是八位產生進位和借位才會設置標志位

所以這個為輔助進位標志位

比如:

3AH + 7CH = B6H,低四位有進位,則AF = 1

DF 方向標志位(Direction Flag)

比如我們的SI 和DI 變址寄存器如果要memcpy的時候,內存會增加或者減少.

DF就是控制地址的變化的方向的

DF = 0,則存儲器地址自動增加

DF = 1,則存儲器的地址自動減少

匯編中的CLD指令,表示復位方向標志,讓其DF = 0,地址自動增加

匯編中的STD指令,表示置位方向標志,DF = 1,表示地址曾東減少.

IF 中斷允許標志(Interrupt - enable Flag)

官方語言: 用於控制外部可屏蔽中斷是否可以被處理器響應

自己理解的

比如鍵盤按下,怎么知道按下的,以前是無限循環,但是效率特別低,現在改成了鍵盤按下就會像CPU發送一個信號

CPU正在執行指令的時候,你按了一下鍵盤,會先放棄當前指令,去執行鍵盤發送過來的按鍵指令,但是如果我們一直按着鍵盤不放,是不是當前的指令就執行不了了,所以我們設置標志即可屏蔽當前發送過來的指令

匯編指令 CLI指令復位中斷標志IF = 0;

匯編指令 STI指令置為中斷標志: IF = 1

IF = 1,則代表我們可以允許中斷(也就是屏蔽指令)

IF = 0,則IF 禁止中斷

TF 陷阱標志(Trap Flag)

用於控制處理器進入單步操作方式(一般調試器才會用到)

TF = 0,處理器正常工作

TF = 1,處理器單步執行指令

利用這個標志,可以對程序進行逐條指令的調試.

這種逐條指令的調試程序的方法就是單步調試,

沒有匯編指令,如果設置,則用 位運算 | 上即可.

 二丶段寄存器以及存儲器

1.存儲器和段寄存器

簡而言之

  說的就是寄存器是cpu內部的內存

  內存可以存放外部數據

  硬盤可以存放外部數據,斷電后還會存在

2.數據的表達單位

  二進制 bit 0 1 組成

  字節 byte 8個bit位組成

  字 word 16位 : 2個字節組成

  雙字DWord 32位,兩個字組成

分為大端模式存儲,和端模式存儲

官方語言是 LSB,MSB等等.小尾方式,和大尾方式

大端模式:  低位放低位地址,高位放到高位地址

低地址 - -------- 高地址 (比如存放1 2 3 4)

0x1  0x2   0x3  0x4

小端模式

低位放高地址,高位放低地址

低地址 - -------- 高地址 (比如存放1 2 3 4)

0x4 0x3 0x2 0x1

3.存儲單元和存儲內容

 每個存儲單元都有一個地址編號,被稱為存儲器的地址,在C語言中其實就是內存地址

每個存儲單元都存放了一個字節的內容.

如果取內容則是

[地址] = 取出來的值,所以C語言中的數組的中括號就是這樣來的.

 4.解決CP的尋址能力

16位處理器,能處理最大的數據范圍是2^16次方數據,也就是64k,就算你裝上一個1MB的內存也訪問不到

解決:

  1.8086CPU有20條地址線,最大的可尋址的控件是2 ^20次方,威力地址從00000h - FFFFFh

  2.8086CPU講1MB的空間分為了很多邏輯段(Segment)

    每個段的最大限制為64kb,為什么,因為寄存器是16位了,沒次尋址都是2 ^16次方

    短地址的低四位為0000b,為什么,因為加了4根地址總線,也就是多了4個,所以都給4

 這樣,一個存儲單元,除了有一個唯一的物理地址,還有很多的邏輯地址

現在為了解決這個尋址問題,所以用2個寄存器存儲,也就是上面為什么說CS和IP一起來確定一條物理內存執行

的下一條指令了.

而邏輯地址有很多,分了好幾段,也就是段地址了, 采用段基地址 : 段內偏移地址 這樣存儲

段地址: 段地址就是邏輯地址在主存的起始位置

  8086規定段的地址必須是%16, 那么地址就是xxxx0H,因為是16進制,所以最后為0,換算成二進制就是后面4個二進制為0

  因為%16地址,所以現在就能用16位的段寄存器來表示段地址了.

偏移地址

  偏移地址說明主存單元距離段地址起始位置的偏移量

  每段也是不超過64kb,也可以用寄存器存儲,所以 IP就出現了

 物理地址和邏輯地址的轉換

講邏輯地址(段地址)左移4位(也就是 *2^4次方)加上偏移的地址,就得到了20位的物理地址

一個物理地址可以有多個邏輯地址

比如

邏輯地址 1460 : 100 物理地址就是14600 (因為*16) + 上偏移100 = 14700H

1380: F00  = 13800 + F00 = 14700H

 

 8086中常用的段寄存器

 CS(代碼段) 指定代碼段的起始地址

SS (堆棧段) 指明了對斬斷的起始地址

DS (數據段) 指明了數據段的起始地址

ES(附加段) 指明了附加端的起始地址

而這些在C語言中稱為內存4區

為什么分段:

  我們上一講寫的顯示Helloworld並且寫到文件中,現在匯編的代碼和數據是在一起的,但是一旦程序更大了,就不好弄了.

作業: 使用debug編譯器,利用指令,查看標志位的狀態顯示分別是什么

第二講作業以及工具獲取連接

鏈接:http://pan.baidu.com/s/1mi3KW1U 密碼:0u0e


免責聲明!

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



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