匯編語言程序

1. 編寫程序的工作過程

編寫程序工作過程
assume cs:codesg
codesg segment
    mov ax,0123H
    mov bx,0456H
    add,ax,bx
    add ax,ax
    mov ax,4c00h
    int 21h
codesg ends
end

2. 匯編程序: 包含匯編指令和偽指令的文本

  • 偽指令: 沒有對應(yīng)的機(jī)器碼的指令, 最終不被cpu 所執(zhí)行, 第1, 2, 9, 10 行代碼

    • 偽指令是由編譯器來執(zhí)行的指令, 編譯器根據(jù)偽指令來進(jìn)行相關(guān)的編譯工作
  • 匯編指令, 對應(yīng)有機(jī)器碼的指令, 可以被編譯為機(jī)器指令, 最終被cpu 執(zhí)行, 3~8 行

  • 程序返回: 程序運(yùn)行結(jié)束后, 將cpu 的控制權(quán)交還給使它得以運(yùn)行的程序, 常為dos 系統(tǒng)

3. 三種偽指令

  • 段定義:
    • 一個(gè)匯編程序是由多個(gè)段組成的, 這些段被用來存放代碼, 數(shù)據(jù)或當(dāng)做??臻g來使用
    • 一個(gè)有意義的匯編程序中至少有一個(gè)段, 這個(gè)段用來存放代碼
    • 定義程序中的段: 每個(gè)段都需要有段名, segment 段開始, end 段結(jié)束
  • end: 匯編程序的結(jié)束標(biāo)記, 若程序結(jié)尾處不是end, 編譯器在編譯程序時(shí), 無法知道程序在何處結(jié)束
  • assume: 含義是假設(shè)某一段寄存器和程序中的某一個(gè)用segment...ends 定義的段相關(guān)聯(lián). assume cs:codesg 指cs 寄存器與codesg 關(guān)聯(lián), 將定義的codesg 當(dāng)做程序的代碼段使用

源程序經(jīng)編譯連接后變?yōu)闄C(jī)器碼

適合編寫大程序, ;注釋符號(hào) 為注釋

4. 編寫程序的步驟

  1. 定義一個(gè)段
  2. 實(shí)現(xiàn)處理任務(wù)
  3. 支出程序在何處結(jié)束
  4. 段與寄存器關(guān)聯(lián)
  5. 加上程序返回的代碼
assume cs:abc
abc segment
    mov ax,2
    add ax,ax
    add ax,ax
    mov ax,4c00h
    int 21h
abc ends
end

程序中可能出現(xiàn)的錯(cuò)誤

  1. 語法錯(cuò)誤

    在編譯時(shí)被編譯器發(fā)現(xiàn)的錯(cuò)誤

  2. 邏輯錯(cuò)誤

    在編譯時(shí)不能表現(xiàn)出來, 在運(yùn)行時(shí)發(fā)生的錯(cuò)誤

5. 源程序到程序運(yùn)行

執(zhí)行文件過程
assume cs:codesg
codesg segment
  mov ax,0123H
  mov bx,0456H
  add ax,ax
  add ax,ax

  mov ax,4c00h
  int 21h
codesg ends
end
masm編譯
  • 目標(biāo)文件(*.obj) 是我們對一個(gè)源程序進(jìn)行編譯得到的最終結(jié)果
  • 列表文件(*.lst) 是編譯器將源程序編譯為目標(biāo)文件過程中產(chǎn)生的中間結(jié)果
  • 交叉引用文件(*.crf) 同列表文件一樣, 是編譯器將源程序編譯為目標(biāo)文件過程中產(chǎn)生的中間結(jié)果
  • 對源程序的編譯結(jié)束, 編譯器輸出的最后兩行告訴我們這個(gè)源程序沒有警告錯(cuò)誤和必須要改正的錯(cuò)誤
  • 命令后加上; 可以簡化流程
link連接文件
  • 可執(zhí)行文件(.exe) 是我們對一個(gè)重新進(jìn)行連接得到的最終結(jié)果
  • 印象文件(.map) 是連接程序?qū)⒛繕?biāo)文件連接為可執(zhí)行文件過程中產(chǎn)生的中間結(jié)果
  • 庫文件(.lib) 里包含了一些可以調(diào)用的子程序, 如果我們的程序中調(diào)用了某一個(gè)庫文件中的子程序, 就需要在連接的時(shí)候, 將這個(gè)庫文件和我們的目標(biāo)文件連接到一起, 生成可執(zhí)行的文件
  • no stack segment, 一個(gè)"沒有棧段" 的警告錯(cuò)誤, 可以不用理會(huì)

執(zhí)行過程, 源文件.asm -> 目標(biāo)文件.obj -> 可執(zhí)行文件.exe

使用debug 裝載程序

debug運(yùn)行
debug裝載程序
  • ds 中存放程序所在區(qū)的段地址, 這個(gè)內(nèi)存的偏移地址為0, 則乘車所在的內(nèi)存區(qū)的地址為ds:0
  • 這個(gè)內(nèi)存區(qū)的前256 字節(jié)存PSP, dos 用來和程序進(jìn)行通信
  • 從256 字節(jié)后的空間存放的是程序, cs 的值為ds+10h
  • 程序加載后, cx 中存放代碼長度

6. [...] 的規(guī)定與(...) 的約定

  • [...] 匯編語法的規(guī)定, 表示一個(gè)內(nèi)存單元
指令 段地址 偏移地址 操作單位
mov ax,[0] DS 中 在[0] 中
mov al,[0] DS 中 在[0] 中 字節(jié)
mov ax,[bx] DS 中 在[bx] 中
mov al,[bx] DS 中 在[bx] 中 字節(jié)
  • (...) 方便學(xué)習(xí)做出的約定, 表示一個(gè)內(nèi)存單元或寄存器中的內(nèi)容
描述對象 描述方法 描述對象 描述方法
ax中的內(nèi)容為0010h (ax)=0010h 2000:1000處的內(nèi)容為0010h (21000h)=0010h
mov ax,[2]的功能 (ax)=((ds)*16+2) mov [2],ax的功能 ((ds)*16+2)=(ax)
add ax,2 的功能 (ax)=(ax)+2 add ax,bx 的功能 (ax)=(ax)+(bx)
push ax 的功能 (sp)=(sp)-2; ((ss)*16 + (sp))=(ax) pop ax 的功能 (ax)=((ss*16)+(sp)); (sp)=(sp)+2

符號(hào)idata 表示常量

mov ax,[idata] 表示, mov ax,[1]

mov bx,idata 表示, mov bx,2

7. Loop 指令

功能: 實(shí)現(xiàn)循環(huán), 計(jì)數(shù)型循環(huán)

指令格式loop 標(biāo)號(hào)

cpu 執(zhí)行l(wèi)oop 指令時(shí)要進(jìn)行的操作

  1. (cx)=(cx)-1
  2. 判斷cx 中的值, 不為0 則跳轉(zhuǎn)至標(biāo)號(hào)處執(zhí)行, 為0 則向下執(zhí)行

注意點(diǎn):

  1. cx 存放循環(huán)次數(shù)
  2. 定義一個(gè)標(biāo)號(hào), 在標(biāo)號(hào)和loop 指令中間寫循環(huán)執(zhí)行的代碼段

實(shí)現(xiàn){2^4}

; loop 指令程序
assume cs:code
code segment
    mov ax,2
    mov cx,3
 s: add ax,ax
    loop s
  
    mov ax,4c00h
    int 21h
code ends
end

8. 段前綴的使用

現(xiàn)象

assume cs:code
code segment
    mov ax,2000h
    mov ds,ax
    mov al,[0]
    mov bl,[1]
    mov cl,[2]
    mov dl,[3]

    mov ax,4c00h
    int 21h
code ends
end
段前綴現(xiàn)象

對策

在[idata] 前顯示寫上段寄存器

mov al,ds:[bx]

mov al,ds:[0]

這些出現(xiàn)在訪問內(nèi)存單元的指令中, 用于顯示的指明內(nèi)存單元段地址的"ds:", "cs:", "ss:", "es", 在匯編語言中稱為段前綴

; 使用附加段寄存器
assume cs:code
code segment
    mov ax,0ffffh
    mov ds,ax
    mov ax,0020h
    mov es,ax

    mov bx,0
    mov cx,12

 s: mov dl,[bx]
    mov es:[bx],dl
    inc bx
    loop s

    mov ax,4c00h
    int 21h
code ends
end

但是以上代碼有問題, 是危險(xiǎn)的

不可以直接寫地址, 這段地址中可能存放其他代碼或者數(shù)據(jù)

應(yīng)該為:

  1. 在程序的段中存放數(shù)據(jù), 運(yùn)行時(shí)由操作系統(tǒng)分配空間
  2. 段的類別, 數(shù)據(jù)段, 代碼段, 棧段
  3. 各種段中均可以有數(shù)據(jù)
  4. 可以在單個(gè)段中安置, 也可以將數(shù)據(jù), 代碼, 棧放入不同的段中
assume cs:code
code segment
    dw 0123H,0456h,0789h,0abch

    mov bx,0
    mov ax,0
    mov cx,4

 s: add ax,cs:[bx]
    add bx,2
    loop s

    mov ax,4c00h
    int 21h
code ends
end

執(zhí)行debug 查看

debug執(zhí)行

代碼混亂, ip 是從0000 開始執(zhí)行, 但是, 段中開始存放的為數(shù)據(jù), 因此需要從0008 開始

改進(jìn)代碼

assume cs:code
code segment
       dw 0123H,0456h,0789h,0abch

start: mov bx,0
       mov ax,0
       mov cx,4

    s: add ax,cs:[bx]
       add bx,2
       loop s

       mov ax,4c00h
       int 21h
code ends
end start
改進(jìn)后執(zhí)行debug

9. 代碼中使用棧

方案一

問題, 將定義的數(shù)據(jù)逆序存放

思路:

  1. 定義的數(shù)據(jù)存在cs:0~cs:f 單元總, 共8 個(gè)字單元
  2. 一次將這8 個(gè)字單元中的數(shù)據(jù)入棧, 然后再一次出棧到8 個(gè)字單元中, 從而實(shí)現(xiàn)數(shù)據(jù)的逆序存放
  3. 棧需要的內(nèi)存空間, 在程序中通過定義空數(shù)據(jù)來取得
assume cs:code
code segment
    dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
    dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

start: mov ax,cs
       mov ss,ax
       mov sp,30h
       mov bx,0 ; 入棧
       mov cx,8
    s: push cs:[bx]
       add bx,2
       loop s

       mov bx,0 ; 出棧
       mov cx,8
   s0: pop cs:[bx]
       add bx,2
       loop s0

       mov ax,4c00h
       int 21h
code ends
end start
逆序排放數(shù)據(jù)
逆序debug執(zhí)行結(jié)果

這種方案數(shù)據(jù)段, 棧, 代碼都在同一個(gè)段中

  • 程序顯得混亂, 編程和閱讀時(shí)都要注意何處是數(shù)據(jù), 何處是棧, 何處是代碼
  • 只應(yīng)用于處理數(shù)據(jù)很少, 用到的??臻g小, 沒多少代碼的情況

我們應(yīng)該將數(shù)據(jù), 棧, 代碼放在不同段中

方案二

修改為:

assume cs:code,ds:data,ss:stack
data segment
  dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
data ends
stack segment
  dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
stack ends
code segment
start: mov ax,stack
       mov ss,ax
       mov sp,20h
       mov ax,data
       mov ds,ax

       mov bx,0
       mov cx,8
    s: push [bx]
       add bx,2
       loop s

       mov bx,0
       mov cx,8
   s0: pop [bx]
       add bx,2
       loop s0

       mov ax,4c00h
       int 21h
code ends
end start
各個(gè)段存放位置
執(zhí)行結(jié)果,內(nèi)存變化
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容