iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 9
2

今天要回頭看第一篇的 Hello World 程式,經過這麼多篇不知道大家有沒有覺得 Hello World 親切許多,回去看 Hello World 絕對不是我沒東西寫了
/images/emoticon/emoticon16.gif

Hello World 程式:

; 定義數據段,存放數據
data segment
    ; db 是定義接下來的數據為單字節的意思,
    ; '$'是字串的結尾,類似 C 的 '\0'
    string db 13,10,'Hello World!',13,10,'$'
data ends

; 定義代碼段,執行的程式碼
code segment
    ; 偽指令,告訴組譯器代碼段的對應
    assume cs:code, ds:data
start:
    mov ax, data     ; 將 data 的地址放到 ax 暫存器
    mov ds, ax       ; 將 ax 的值放到 ds 暫存器
    lea dx, string   ; 將 string 變數的地址放進 dx 暫存器
    mov ah, 09h      ; 09h 對應的是將字串輸出到螢幕上
    int 21h          ; 調用系統功能,對應的是目前 ah 暫存器中的值

    mov ax, 4c00h    ; 退出程式
    int 21h          ; 調用系統功能
code ends

end start   ; 讓組譯器知道程式的進入點

偽指令

組合語言的指令分為一般指令和偽指令,一般指令是指可以直接被對應成機器碼的指令,例如 mov、add,而偽指令是給編譯器看的,實際上並不會被編譯為機器碼。

  • segment 和 ends

segment 和 ends 用來定義一個段,一個程式最少需要代碼段才能正常執行,段的名稱是可以自訂的,並不一定要用 data 或 code。

  • assume

assume 用於告訴編譯器段暫存器和段的對應關係,例如 ds:data 就代表 data 是數據段,比較難理解的是 assume 並不會改變段暫存器內容,程式中還是需要用 mov 指令將 data 的地址指定給 ds 暫存器,Google 後找到的內容是寫 assume 會影響編譯後執行檔開頭的描述訊息,但並不是很理解,有經驗的大大可以幫我補充一下。

  • end

end 代表程式的結尾,而 end 後面接著的標號就是程式的入口點,cs 和 ip 不像 ds 需要在程式內指定,作業系統將 CPU 控制權交給程式時,會自動把 CS 和 IP 設在程式的入口點上,入口標號同樣也可以自訂名稱,不一定要用 start。

標號『:』

標號代表一個記憶體地址,可以搭配其他指令使用,例如 end、jmp,等等。

int 21h 中斷

在講 int 21h 之前要先知道程式是如何執行的,電腦開機後首先執行 BIOS 程式,接著才會載入作業系統,之後 CPU 的控制權就會交給作業統,而要執行我們的程式,需要作業系統再把控制權交給程式,程式結束後返還控制權,因為 DOS 一次只能執行一個程式,所以如果程式結束後沒有正確的返還控制權給作業系統,電腦就會卡住不動了。

程式中的 int 21h 就是用來結束程式並將 CPU 控制權還給作業系統,int 21h 用於調用系統功能,而要調用的功能則看 ah 暫存器中的值,例如 int 21h 的上一段指令 mov ax, 4c00h,4c 對應的功能就是退出程式,中斷在 DOS 作業系統是非常重要的概念,之後會再詳細介紹。

快速編譯程式

第一篇介紹過可以使用 masmlink 編譯程式,但每次都需要執行兩個步驟實在麻煩,這裡介紹一個更快速的方法。

ml hello.asm

ml 等於 masm + link,一個步驟就完成編譯。

PSP

執行檔 .exe 是如何被加載執行的呢?

  1. 從硬碟中讀取 .exe 內容
  2. 在記憶體中建立 PSP 區塊並載入程式
  3. 使用 PSP 地址初始化 DS 和其他相關暫存器
  4. 初始化 CS 和 IP 在第一行指令的地方
  5. 將 CPU 控制權交給程式並執行第一行指令

其中 PSP 是一個 256 字節大小的區域,位於程式之前,主要用於程式和 DOS 作業系統間的資訊交流,程式加載的過程中會將 DS 設在 PSP 的段地址上,所以程式中才需要另外將 DS 指定到我們定義的數據段上,因為 PSP 和程式位於不同的段上。

PSP 示意圖:

https://ithelp.ithome.com.tw/upload/images/20181024/20106865hzdyomvzZ5.jpg

結語

不知道大家看懂 Hello World 了嗎?
寫到第九篇才算完整介紹完 Hello World,疑~不對好像還有變數沒講,這真是一條艱難的路阿!!!,哈哈哈。

今天就到這裡摟,感謝大家觀看。


上一篇
[Day08] 棧段暫存器
下一篇
[Day10] 循環指令 - loop
系列文
8086下16位元DOS組合語言學習筆記12

尚未有邦友留言

立即登入留言