匯編基礎(chǔ)(三)

編寫一個完整的匯編

assume cs:code   ;這是一個注釋
code segment
  mov ax,1122h
  mov bx,3344h
  add ax,bx

  mov ah,4ch
  int 21h
code ends
end

匯編語言由2類指令組成
1.匯編指令
如mov、add、sub等
有對應的機器指令,可以被編譯為機器指令,最終被CPU執(zhí)行

2.偽指令
如assume、 segment、ends、end等
沒有對應的機器指令,由編譯器解析,最終不被CPU執(zhí)行

3.注釋以分號開頭

偽指令 - segment , ends , end

segment和ends的作用是定義一個段,segment代表一個段的開始,ends代表一個段的結(jié)束,使用格式為

段名 segment
:
段名 ends

一個有意義的匯編程序中,至少要有一個段作為代碼段存放代碼
assume
將用作代碼段的code段和CPU中的cs寄存器關(guān)聯(lián)起來
end
編譯器遇到end時,就結(jié)束對源程序的編譯
下面2句代碼的作用是退出程序

中斷

mov ah,4ch
int 21h
;也可以寫成 mov ax, 4c00h  int 21h

中斷是由于軟件的或硬件的信號,使得CPU暫停當前的任務,轉(zhuǎn)而去執(zhí)行另一段子程序
也就是說,在程序運行過程中,系統(tǒng)出現(xiàn)了一個必須由CPU立即處理的情況,此時,CPU暫時中止當前程序的執(zhí)行轉(zhuǎn)而處理這個新情況的過程就叫做中斷

中斷的分類
硬中斷(外中斷),由外部設備(比如網(wǎng)卡、硬盤)隨機引發(fā)的,比如當網(wǎng)卡收到數(shù)據(jù)包的時候,就會發(fā)出一個中斷
軟中斷(內(nèi)中斷),由執(zhí)行中斷指令產(chǎn)生的,可以通過程序控制觸發(fā)

從本質(zhì)上來講,中斷是一種電信號,當設備有某種事件發(fā)生時,它就會產(chǎn)生中斷,通過總線把電信號發(fā)送給中斷控制器。如果中斷的線是激活的,中斷控制器就把電信號發(fā)送給處理器的某個特定引腳。處理器于是立即停止自己正在做的事,跳到中斷處理程序的入口點,進行中斷處理

可以通過指令int n產(chǎn)生中斷
n是中斷碼,內(nèi)存中有一張中斷向量表,用來存放中斷碼對應中斷處理程序的入口地址
CPU在接收到中斷信號后,暫停當前正在執(zhí)行的程序,跳轉(zhuǎn)到中斷碼對應的中斷向量表地址處,去執(zhí)行中斷處理程序

  • 常見中斷
    • int 10h用于執(zhí)行BIOS中斷
    • int 3是“斷點中斷”,用于調(diào)試程序
    • int 21h用于執(zhí)行DOS系統(tǒng)功能調(diào)用,AH寄存器存儲功能號

DOS系統(tǒng)功能調(diào)用

DOS系統(tǒng)功能調(diào)用
由DOS提供的一組實現(xiàn)特殊功能的子程序供程序員在編寫自己的程序時調(diào)用,以減輕編程的工作量
涉及屏幕顯示、文件管理、I/O管理等等
每個子程序都有一個功能號,所有的功能調(diào)用的格式都是一致的。調(diào)用的步驟大致如下:

系統(tǒng)功能號送到寄存器AH中;
入口參數(shù)送到指定的寄存器中;
用INT 21H指令執(zhí)行功能調(diào)用;
根據(jù)出口參數(shù)分析功能調(diào)用執(zhí)行情況。


;----數(shù)據(jù)段---
data segment
string db 'Hello World!$'
data ends
mov ax, data
mov ds, ax ; 設置ds為數(shù)據(jù)段

mov ah,9h ;功能號9h代表在屏幕顯示字符串
mov dx, offset string ;ds:dx代表字符串地址
int 21h ;執(zhí)行DOS系統(tǒng)功能調(diào)用

Loop指令

loop指令和cx寄存器配合使用,用于循環(huán)操作類似高級語言的for,while
使用格式
mov cx,循環(huán)次數(shù)
標號:
循環(huán)執(zhí)行的程序代碼
loop 標號
loop指令執(zhí)行流程
步驟1 先將cx寄存器的值 - 1, cx = cx - 1
步驟2 判斷cx 的值
如果不為零執(zhí)行標號的代碼,又執(zhí)行 步驟 1
如果為零執(zhí)行l(wèi)oop后面的代碼
補充:
獲取數(shù)據(jù),除了通過ds段來獲取.還可以利用其它段地址來獲取
mov ax,ds:[0]
mov ax,cs:[0]
mov ax,ss:[0]
mov ax,es:[0]
8086偽指令

db(define byte) 自定義字節(jié)
dw(define word)自定義字
Call和ret指令

Call指令

call標號
將下一條指令的偏移地址入棧!
跳轉(zhuǎn)到定位的地址執(zhí)行指令!
ret指令

ret指令就是將棧頂?shù)闹礟OP給IP

案例


assume cs:code   

code segment
mov ax ,ffffH
mov ds ,ax

mov dx,0h 
mov bx,0h
mov cx,3h   
   
s: mov al,[bx]  ;ff   
mov ah,0
add dx,ax
add bx,1h
loop s

mov ah,4ch
int 21h

code ends 

end
assume  cs:code,ds:data,ss:stack  

;棧段(存放數(shù)據(jù),比如高級語言中的局部變量)
stack segment 
    db 20 dup(0)
stack ends

;數(shù)據(jù)段(存放數(shù)據(jù),比如高級語言中的全局變量)
data segment   
     db 20 dup(0)
     str db "Hello World!$"    
data ends

;代碼段
code segment
start: 
    ;設置ds和ss
    mov ax,data
    mov ds,ax
    mov ax,stack
    mov ss,ax


    ;業(yè)務邏輯代碼 
    call print
    mov ax,1122h   
    ;退出程序
    mov ah,4ch
    int 21h  
print: 
    mov ax,3344h
    push ax   
    mov dx,offset str;offset 獲得標號對應的偏移
    mov ah,9h
    int 21h 
    pop ax
    ret   
code ends
end start
assume  cs:code,ds:data,ss:stack  

;棧段(存放數(shù)據(jù),比如高級語言中的局部變量)
stack segment 
    db 20 dup(0)
stack ends

;數(shù)據(jù)段(存放數(shù)據(jù),比如高級語言中的全局變量)
data segment   
     db 20 dup(0)             
data ends

;代碼段
code segment
start: 
    ;設置ds和ss
    mov ax,data
    mov ds,ax
    mov ax,stack
    mov ss,ax


    ;業(yè)務邏輯代碼 
    mov bx,3h
    mov dx,4h
    call sum
    
    
      
    ;退出程序
    mov ah,4ch
    int 21h   
    ;參數(shù):傳遞兩個字型參數(shù),參數(shù)分別用bx,dx存放
    ;返回值:返回值存放在ax中
 sum:   
     mov ax,bx
     add ax,dx
     ret
      
code ends
end start
assume  cs:code,ds:data,ss:stack  

;棧段(存放數(shù)據(jù),比如高級語言中的局部變量)
stack segment 
    db 20 dup(0)
stack ends

;數(shù)據(jù)段(存放數(shù)據(jù),比如高級語言中的全局變量)
data segment   
     db 20 dup(0)             
data ends

;代碼段
code segment
start: 
    ;設置ds和ss
    mov ax,data
    mov ds,ax
    mov ax,stack
    mov ss,ax


    ;業(yè)務邏輯代碼
    push 1h
    push 3h
    push 4h
    call sum
    ;add sp,6   
    push 1h
    push 3h
    push 4h
    call sum
    ;add sp,6 
    push 1h
    push 3h
    push 4h
    call sum
    ;add sp,6 
    
    
      
    ;退出程序
    mov ah,4ch
    int 21h   
    ;參數(shù):傳遞兩個字型參數(shù),參數(shù)分別用bx,dx存放
    ;返回值:返回值存放在ax中
 sum:
     mov bp,sp   
     mov ax,ss:[bp + 2] 
     add ax,ss:[bp + 4]
     add ax,ss:[bp + 6]
     ret 6
      
code ends
end start
;函數(shù)棧平衡:保證函數(shù)調(diào)用前后的棧頂是一致的
;1.外平棧:由函數(shù)外部保持棧平衡
;2.內(nèi)平棧:由函數(shù)內(nèi)部保持棧平衡
assume  cs:code,ds:data,ss:stack  

;棧段(存放數(shù)據(jù),比如高級語言中的局部變量)
stack segment 
    db 20 dup(0)
stack ends

;數(shù)據(jù)段(存放數(shù)據(jù),比如高級語言中的全局變量)
data segment   
     db 20 dup(0)
     str db "Hello World!$"    
data ends

;代碼段
code segment
start: 
    ;設置ds和ss
    mov ax,data
    mov ds,ax
    mov ax,stack
    mov ss,ax


    ;業(yè)務邏輯代碼 
    call print
    mov ax,1122h   
    ;退出程序
    mov ah,4ch
    int 21h  
print: 
    mov ax,3344h
    push ax   
    mov dx,offset str;offset 獲得標號對應的偏移
    mov ah,9h
    int 21h 
    pop ax
    ret   
code ends
end start
assume  cs:code,ds:data,ss:stack  

;棧段(存放數(shù)據(jù),比如高級語言中的局部變量)
stack segment 
    db 20 dup(0)
stack ends

;數(shù)據(jù)段(存放數(shù)據(jù),比如高級語言中的全局變量)
data segment   
     db 20 dup(0)
     str db "Hello World!$"              
data ends

;代碼段
code segment
start: 
    ;設置ds和ss
    mov ax,data
    mov ds,ax
    mov ax,stack
    mov ss,ax


    ;業(yè)務邏輯代碼
    push 3h    ;傳遞參數(shù)
    push 4h
    call sum
    ;add sp,6   
    
    
      
    ;退出程序
    mov ah,4ch
    int 21h   
    ;參數(shù):傳遞兩個字型參數(shù),參數(shù)分別用bx,dx存放
    ;返回值:返回值存放在ax中
 sum:
     ;保護bp
     push bp
     mov bp,sp    
     sub sp,20  ;20字節(jié)留作局部變量 
     ;保護寄存器
     push bx
     push cx
     push dx
     ;*****************業(yè)務邏輯代碼
     ;定義兩個局部變量
     mov ss:[bp - 2],1h
     mov ss:[bp - 4],2h  
     
     ;修改寄存器
     mov bx,2h
     mov cx,3h
     mov dx,4h  
     
     mov ax,ss:[bp + 2] 
     add ax,ss:[bp + 4] 
     add ax,ss:[bp - 2]
     add ax,ss:[bp - 4]  
     ;*****************業(yè)務邏輯代碼 
     ;恢復寄存器
     pop dx
     pop cx
     pop bx
     
     ;恢復sp
     mov sp,bp   
     ;恢復bp
     pop bp
     
     ret 4  
      
code ends
end start
;函數(shù)棧平衡:保證函數(shù)調(diào)用前后的棧頂是一致的
;1.外平棧:由函數(shù)外部保持棧平衡
;2.內(nèi)平棧:由函數(shù)內(nèi)部保持棧平衡 



;int sum(int a, int b)
;{
;    int c = 1;
;    int d = 2;
;    return a + b + c + d;
;}
;函數(shù)的調(diào)用流程
;1.push參數(shù)(64位cpu 任性使用寄存器)
;2.call指令調(diào)用(將下一條指令地址入棧)
;3.保護bp寄存器,將sp賦值給bp
;4.提升sp指針,作為局部變量空間(sp 減去值)
;5.保護寄存器
;6.業(yè)務邏輯
;7.恢復寄存器
;8.恢復sp(sp指向bp/sp 加上值)
;9.恢復bp(pop bp)
;10.返回(ret)

emu8086常用快捷鍵

  • F5:調(diào)試運行

  • F4:重新加載

  • F8:下一步(單步執(zhí)行)

  • F9:直接一步到位運行整個程序

  • Ctrl + F8:跳過前面代碼,斷點到單擊選中的代碼那行

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

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

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