彙編語言Assembly(二)

各指令:

mov數據傳送指令指令:兩個操作數的數據類型要相同,兩個操作數不能同時爲段寄存器,代碼段寄存器CS不能爲目的操作數,但可作爲源操作數。立即數不能直接傳給段寄存器,立即數不能作爲目的操作數,指令指針IP,不能作爲MOV指令的操作數。兩個操作數不能同時爲存儲單元,就是一條指令不能兩次訪存。

符號擴展是用源操作數的符號位來填充目的操作數的高位數據位,指令movsx。零擴展是用0來填充目的操作數的高位數據位,指令movzx。

交換指令xchg交換寄存器和內存單元中的值,該寄存器不能是段寄存器。

指令lea是把一個內存變量的有效地址送給指定的寄存器。該指令通常用來對指針或變址寄存器BX、DI或SI等置初值。

入棧指令push,出棧指令pop。PUSHF/PUSHFD把16位/32位標誌寄存器進棧;POPF/POPFD把16位/32位標誌寄存器出棧。

clc:置進位標誌位cf爲0.

stc:置進位標誌位cf爲1.

進位取反指令cmc:取反cf位。

cld :置方向標誌位df爲0.

std:置方向位指令df爲1.

清中斷允許位指令cli置IF爲0,使得不允許可屏蔽的外部中斷來中斷其後程序段的執行。置中斷允許位指令sti置IF爲1,恢復可屏蔽的外部中斷的中斷響應功能。

加法指令ADD,帶進位的加法指令ADC,把源操作數和進位標誌位CF的值(0/1)一起加到目的操作數中。加一指令INC。與之對應的減法指令SUB SBB DEC,求補指令DEG。無符號乘法指令MUL,有符號乘法指令IMUL。無符號除法指令DIV , 有符號除法指令IDIV。邏輯與AND,邏輯或OR,邏輯異或XOR,邏輯非NOT。算術左移SAL,算法右移SAR,算術移位是低位補0,高位補符號位。邏輯左移SHL,邏輯右移SHR,邏輯移位是低位和高位都補0。雙精度左移SHLD,SHLD/SHRD  Reg/Mem, Reg, n,在執行SHLD指令時,第一操作數向左移n位,其“空出”的低位由第二操作數的高n位來填補。循環左移ROL和循環右移ROR,它們移出的位不僅要進入CF,而且還要填補空出的位。帶進位的循環左移RCL和帶進位的循環右移RCR,它們都用原CF的值填補空出的位,移出的位再進入CF。位掃描指令BSF和BSR,位掃描指令是在第二個操作數中找第一個“1”的位置。如果找到,則該“1”的位置保存在第一操作數中,並置標誌位ZF爲1,否則,置標誌位ZF爲0,BSF是從低位向高位掃,BSR相反。檢測位指令test,把兩個操作數進行邏輯“與”操作,並根據運算結果設置相應的標誌位,但並不保存該運算結果,所以,不會改變指令中的操作數。比較指令CMP,用第二個數減去第一個數,根據結果設置各標誌位。循環指令loop,循環次數存放在CX中。指令jcxz,當CX=0時,則程序轉移標號處執行。無條件指令jmp tag。

條件跳轉指令:

   無符號數條件轉移指令:

指令的助憶符

檢測的轉移條件 功能描述

JE/JZ

ZF=1 Jump Equal or Jump Zero

JNE/JNZ

ZF=0 Jump Not Equal or Jump Not Zero

JA/JNBE

CF=0 and ZF=0 Jump Above or Jump Not Below or Equal

JAE/JNB

CF=0 Jump Above or Equal or Jump Not Below

JB/JNAE

CF=1 Jump Below or Jump Not Above or Equal

JBE/JNA

CF=1 or AF=1 Jump Below or Equal or Jump Not Above
   有符號數條件轉移指令:

指令的助憶符

檢測的轉移條件 功能描述

JE/JZ

ZF=1 Jump Equal or Jump Zero

JNE/JNZ

ZF=0 Jump Not Equal or Jump Not Zero

JG/JNLE

ZF=0 and SF=OF Jump Greater or Jump Not Less or Equal

JGE/JNL

SF=OF Jump Greater or Equal or Jump Not Less

JL/JNGE

SF≠OF Jump Less or Jump Not Greater or Equal

JLE/JNG

ZF=1 or SF≠OF Jump Less or Equal or Jump Not Greater
特殊算術標誌位的條件轉移指令:

指令的助憶符

檢測的轉移條件 功能描述

JC

CF=1 Jump Carry

JNC

CF=0 Jump Not Carry

JO

OF=1 Jump Overflow

JNO

OF=0 Jump Not Overflow

JP/JPE

PF=1 Jump Parity or Jump Parity Even

JNP/JPO

PF=0 Jump Not Parity or Jump Parity Odd

JS

SF=1 Jump Sign (negative)

JNS

SF=0 Jump No Sign (positive)
條件設置指令set系列是在386之後的CPU中出現的。


字符串操作指令是對一片連續存儲單元進行處理,這片存儲單元是由隱含指針DS:SI或ES:DI來指定的。字符串操作指令可對內存單元按字節、字或雙字進行處理,並能根據操作對象的字節數使變址寄存器SI(和DI)增減1、2或4。當DF=0時,變址寄存器SI(和DI)增加1、2或4;當DF=1時,變址寄存器SI(和DI)減少1、2或4。取字符串數據指令LODS,從由指針DS:SI所指向的內存單元開始,取一個字節、字或雙字進入AL、AX或EAX中,並根據標誌位DF對寄存器SI作相應增減。該指令的執行不影響任何標誌位。置字符串數據指令STOS,該指令是把寄存器AL、AX或EAX中的值存於以指針ES:DI所指向內存單元爲起始的一片存儲單元裏,並根據標誌位DF對寄存器DI作相應增減。該指令不影響任何標誌位。字符串傳送指令MOVS,該指令是把指針DS:SI所指向的字節、字或雙字傳送給指針ES:DI所指向內存單元,並根據標誌位DF對寄存器DI和SI作相應增減。該指令的執行不影響任何標誌位。輸入字符串指令ints,輸出字符串指令outs。字符串比較指令cmps,該指令是把指針DS:SI和ES:DI所指向字節、字或雙字的值相減,並用所得到的差來設置有關的標誌位。重複前綴指令REP根據CX值確定重複執行後面的指令多少次。條件重複前綴指令,根據CX和zf值確定是否重複和重複幾次,REPE和REPZ根據CX≠0 且 ZF=1則重複,REPNE和REPNZ根據CX≠0 且 ZF=0重複。

空指令操作NOP,等待指令WAIT,暫停指令HLT:在等待中斷信號時,該指令使CPU處於暫停工作狀態,CS:IP指向下一條待執行的指令。當產生了中斷信號,CPU把CS和IP壓棧,並轉入中斷處理程序。在中斷處理程序執行完後,中斷返回指令IRET彈出IP和CS,並喚醒CPU執行下條指令。封鎖數據指令LOCK。


彙編程序可定義多個段,數據段、棧端、多個代碼段,每段有自己的段名:name segment........name ends。通過assume僞指令每個段都要與一個段寄存器建立一種對應關係:ASSUME  段寄存器名:段名[,段寄存器名:段名, ……]。要定義堆棧段,來用壓棧和出棧對方法和數據進行操作。僞指令END寫在最後。


採用CMP和有條件跳轉指令或無條件跳轉指令配合達到if/else判斷形成分支結構程序的目的。竟然還有類C的僞指令:.IF  .ELSEIF  .ELSE  .ENDIF可以協助進程分支程序的設計。僞指令.WHILE   .REPEAT協助設計循環程序結構。還有.BREAK  .CONTUNUE來進程中斷循環。


  DATA1 SEGMENT
data DW 90, 95, 54, 65, 36, 78, 66, 0, 99, 50, -1
Average DW 0
DATA1 ENDS
CODE1 SEGMENT
ASSUME CS:CODE1, DS:DATA1
START: MOV AX, DATA1
MOV DS, AX
XOR AX, AX
XOR DX, DX ;用(DX,AX)來保存數組元素之和
XOR CX, CX ;用CX來保存數組元素個數
LEA SI, data ;用指針SI來訪問整個數組
again: MOV BX, word ptr [SI]
CMP BX, 0
JL over
ADD AX, BX
ADC DX, 0 ;把當前數組元素之值加到(DX,AX)中
INC CX ;數組元素個數加1
ADD SI, 2
JMP again
over: JCXZ exit ;防止零作除數,即數組是空數組
DIV CX
MOV Average, AX
exit: MOV AX, 4C00H
INT 21H
CODE1 ENDS
END START

段組僞指令GROUP是用於把源程序模塊中若干個段結合成一個組,並對該段組定義一個段組名。段組僞指令的格式如下:段組名  GROUP  段名[, 段名,……]。


子程序調用指令CALL  子程序名/deg/mem。若是近調用,CALL指令將產生一個近調用,它把該指令之後地址的偏移量(用一個字來表示的)壓棧,把被調用子程序入口地址的偏移量送給指令指針寄存器IP即可實現執行程序的轉移。若是遠調用,調用指令不僅要把該指令之後地址的偏移量壓進棧,而且也要把段寄存器CS的值壓進棧。在此之後,再把被調用子程序入口地址的偏移量和段值分別送給IP和CS,這樣完成了子程序的遠調用操作。子程序返回指令RET/RETF/RETN,在近類型的子程序中,返回指令RET是近返回,其功能是把棧頂之值彈出到指令指針寄存器IP中,SP會被加2;若是遠返回,則先出棧至IP,再出棧至CS,同時SP加4。

而子程序是需要傳遞參數的,一般是寄存器傳參、內存單元存放參數和棧保存參數。寄存器傳參適用於參數少的子程序因爲寄存器本身就少。內存地址存放需要指定位置存放和取得參數。當用堆棧傳遞入口參數時,要在調用子程序前把有關參數依次壓棧,子程序從堆棧中取到入口參數;當用堆棧傳遞出口參數時,要在子程序返回前,把有關參數依次壓棧(這裏還需要做點額外操作,要保證返回地址一定在棧頂),調用程序就可以從堆棧中取到出口參數。在子程序中,保存和恢復寄存器內容的主要方法是:在子程序的開始把它所用到的寄存器壓進棧,在返回前,再把它們彈出棧。這樣編寫的好處是該子程序可以被任何其它程序來調用。在調用指令前,不需要保存寄存器,在調用指令後,也無需恢復寄存器。

子程序僞指令invoke類似於call。僞指令LOCAL來說明一個或者多個局部變量:LOCAL 變量名[數量][:數據類型],.......。僞指令PUBLIC tag1, tag2.......說明這些標識符可以爲其他模塊引用的公共標識符。僞指令EXTERN tag1:type, tag2:type......說明這些標識符已經在其他模塊中定義了。類似於C語言。


CPU區分不同的I/O設備使用I/O端口,形成端口地址空間。主要的端口地址:

端口地址 端口名稱 端口地址 端口名稱

020H~023H

中斷屏蔽寄存器

378H~37FH

並行口LPT2

040H~043H

時針/計數器

3B0H~3BBH

單色顯示器端口

060H

鍵盤輸入端口

3BCH~3BFH

並行口LPT1

061H

揚聲器(0, 1位)

3C0H~3CFH

VGA/EGA

200H~20FH

遊戲控制口

3D0H~3DFH

CGA

278H~27FH

並行口LPT3

3F0H~3F7H

磁盤控制器

2F8H~2FFH

串行口COM2

3F8H~3FFH

串行口COM1

計算機在啓動時,BIOS程序(BasicInput/Output System)將檢查計算機系統中有哪些端口地址。當發現有串行端口地址時,BIOS就把該端口存放在以地址40:00H開始的數據區內;當發現有並行端口地址時,BIOS會把它存入以地址40:08H開始的數據區內。每個端口有4個字空間。針對於端口的指令只有IN和OUT,例如IN AX ,60H把端口地址60H和61H按照高對高低對低的順序存儲在AX中。

中斷分爲外部中斷和內部中斷,分爲可屏蔽中斷和不可屏蔽中斷,分爲硬件中斷和軟件中斷,由中斷控制器interupter handler控制。中斷類型以中斷類型碼指示,利用中斷向量表來指示中斷向量地址即中斷處理程序開始地址。主要中斷號:

中斷號 含義 中斷號 含義
0 除法出錯 8 定時器
1 單步 9 鍵盤
2 非屏蔽中斷 A 未用
3 斷點 B COM2
4 溢出 C COM1
5 打印屏幕 D 硬盤(並行口)
6 未用 E 軟盤
7 未用 F 打印機
中斷指令INT num,中斷返回指令IRET。


彙編中也有宏的概念,利用宏名來代替一段程序代碼。宏定義:

宏名  MACRO [參數]

   ........宏主體

宏名 ENDM

而宏的引用形式爲:宏名 [參數]。參數可以是常量、寄存器、表達式、內存地址。宏內可以引用其他宏,可以定義宏。“PURGE 宏名”表示解除宏定義。宏可以進行宏擴展。


要在C語言中嵌入彙編語言,可以asm mov ax,data,可以嵌入一組asm {........}。



難點:使用棧來存儲參數,會使得數據和地址都存在棧裏面。當用棧傳遞入口參數時要在子程序前把有關參數依次壓棧,子程序從堆棧中取得參數;;當用棧傳遞出口參數時要在子程序返回之前把有關參數依次壓棧而且要保證返回地址一定在棧頂。如果是段內調用,call指令會把IP值壓棧,子程序要用BP來訪問棧,所以子程序要先保存BP的值在棧中,再把當前SP即棧頂偏移量傳給BP,用BP來取得參數:

子程序寄存器保存後的棧

  SUBPRO PROC  NEAR
PUSH BP ;保護寄存器BP
MOV BP, SP ;用寄存器BP來訪問堆棧,讀取參數
;保護其它寄存器的指令
MOV Paran, [BP+4] ;保護其它寄存器的指令
MOV Para1, [BP+4+2*(n-1)]
SUBPRO ENDP
段間調用只是由於call將IP和CS值相繼壓棧,所以子程序取得參數時的相對於BP的偏移量與段內調用有所差異:



彙編語言代碼段:

  DATA1 SEGMENT
data DW 90, 95, 54, 65, 36, 78, 66, 0, 99, 50, -1
Average DW 0
DATA1 ENDS
CODE1 SEGMENT
ASSUME CS:CODE1, DS:DATA1
START: MOV AX, DATA1
MOV DS, AX
XOR AX, AX
XOR DX, DX ;用(DX,AX)來保存數組元素之和
XOR CX, CX ;用CX來保存數組元素個數
LEA SI, data ;用指針SI來訪問整個數組
again: MOV BX, word ptr [SI]
CMP BX, 0
JL over
ADD AX, BX
ADC DX, 0 ;把當前數組元素之值加到(DX,AX)中
INC CX ;數組元素個數加1
ADD SI, 2
JMP again
over: JCXZ exit ;防止零作除數,即數組是空數組
DIV CX
MOV Average, AX
exit: MOV AX, 4C00H
INT 21H
CODE1 ENDS
END START


  DATA1 SEGMENT
data DW 90, 95, 54, 65, 36, 78, 66, 0, 99, 50, -1
Average DW 0
DATA1 ENDS
CODE1 SEGMENT
ASSUME CS:CODE1, DS:DATA1
START: MOV AX, DATA1
MOV DS, AX
XOR AX, AX
XOR DX, DX ;用(DX,AX)來保存數組元素之和
XOR CX, CX ;用CX來保存數組元素個數
LEA SI, data ;用指針SI來訪問整個數組
again: MOV BX, word ptr [SI]
CMP BX, 0
JL over
ADD AX, BX
ADC DX, 0 ;把當前數組元素之值加到(DX,AX)中
INC CX ;數組元素個數加1
ADD SI, 2
JMP again
over: JCXZ exit ;防止零作除數,即數組是空數組
DIV CX
MOV Average, AX
exit: MOV AX, 4C00H
INT 21H
CODE1 ENDS
END START

  DATA1 SEGMENT
MSG1 DB 13, 10,  "Iteration: "
NUM1 DB '1', "$"
MSG2 DB 13, 10,  "Alphabet: $"
NUM2 DB 'A', " $"
MSG3 DB 13, 10, "Type digits, then press ENTER: $"
DATA1 ENDS
CODE1 SEGMENT
ASSUME CS:CODE1, DS:DATA1
START: MOV AX, DATA1
MOV DS, AX
MOV CX,9
MOV AH, 09H
MOV DX, OFFSET MSG1
.REPEAT
INT 21H
INC NUM1
;顯示Iteration: 1,2,~,9
.UNTILCXZ
MOV DX,OFFSET MSG2
INT 21H ;顯示字符串"Alphabet:"
MOV AH, 09H
MOV DX, OFFSET NUM2
.REPEAT
INT 21H
INC NUM2
;顯示當前字母
;當前字母向後移
.UNTIL NUM2 > 'Z' ;顯示整個大寫字母表
MOV AH, 09H
MOV DX, OFFSET MSG3
INT 21H
.WHILE  1 ;循環條件爲永真的循環
MOV AH, 07H
INT 21H
;不帶回顯地從鍵盤讀一個字符
.BREAK .IF AL == 13 ;如果輸入“回車”鍵,則終止循環
.CONTINUE .IF(AL<'0') || (AL>'9') ;如果字符不是數字字符,則繼續循環
MOV DL, AL
MOV AH, 02H
INT 21H
;顯示所輸入的數字字母
.ENDW
MOV AX, 4C00H
INT 21H
CODE1 ENDS
END START

參考資料:

   http://www.feiesoft.com/asm/07-3-3.html

  DATA1 SEGMENT
data DW 90, 95, 54, 65, 36, 78, 66, 0, 99, 50, -1
Average DW 0
DATA1 ENDS
CODE1 SEGMENT
ASSUME CS:CODE1, DS:DATA1
START: MOV AX, DATA1
MOV DS, AX
XOR AX, AX
XOR DX, DX ;用(DX,AX)來保存數組元素之和
XOR CX, CX ;用CX來保存數組元素個數
LEA SI, data ;用指針SI來訪問整個數組
again: MOV BX, word ptr [SI]
CMP BX, 0
JL over
ADD AX, BX
ADC DX, 0 ;把當前數組元素之值加到(DX,AX)中
INC CX ;數組元素個數加1
ADD SI, 2
JMP again
over: JCXZ exit ;防止零作除數,即數組是空數組
DIV CX
MOV Average, AX
exit: MOV AX, 4C00H
INT 21H
CODE1 ENDS
END START
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章