久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

匯編語言超濃縮教程

 intruder 2005-11-04

    匯編語言超濃縮教程

“ 哎喲,哥們兒,,還搗鼓匯編呢,?那東西沒用,兄弟用VB"釣"一個API就夠你忙活個十天半月的,,還不一定搞出來,。”此君之言倒也不虛,那吾等還有無必要研他一究呢,?(廢話,,當(dāng)然有啦!要不然你寫這篇文章干嘛,。)別急,,別急,讓我把這個中原委慢慢道來:一,、所有電腦語言寫出的程序運(yùn)行時在內(nèi)存中都以機(jī)器碼方式存儲,機(jī)器碼可以被比較準(zhǔn)確的翻譯成匯編語言,,這是因?yàn)閰R編語言兼容性最好,,故幾乎所有跟蹤、調(diào)試工具(包括WIN95/98下)都是以匯編示人的,,如果閣下對CRACK頗感興趣……,;二,、匯編直接與硬件打交道,如果你想搞通程序在執(zhí)行時在電腦中的來龍去脈,,也就是搞清電腦每個組成部分究竟在干什么,、究竟怎么干?一個真正的硬件發(fā)燒友,,不懂這些可不行,。三、如今玩DOS的多是“高手”,,如能像吾一樣混入(我不是高手)“高手”內(nèi)部,,不僅可以從“高手”朋友那兒套些黑客級“機(jī)密”,還可以自詡“高手”盡情享受強(qiáng)烈的虛榮感--#$%& “醒醒!”

  對初學(xué)者而言,,匯編的許多命令太復(fù)雜,,往往學(xué)習(xí)很長時間也寫不出一個漂漂亮亮的程序,以致妨礙了我們學(xué)習(xí)匯編的興趣,,不少人就此放棄,。所以我個人看法學(xué)匯編,不一定要寫程序,,寫程序確實(shí)不是匯編的強(qiáng)項(xiàng),,大家不妨玩玩DEBUG,有時CRACK出一個小軟件比完成一個程序更有成就感(就像學(xué)電腦先玩游戲一樣),。某些高深的指令事實(shí)上只對有經(jīng)驗(yàn)的匯編程序員有用,,對我們而言,太過高深了,。為了使學(xué)習(xí)匯編語言有個好的開始,,你必須要先排除那些華麗復(fù)雜的命令,將注意力集中在最重要的幾個指令上(CMP LOOP MOV JNZ……),。但是想在啰里吧嗦的教科書中完成上述目標(biāo),,談何容易,所以本人整理了這篇超濃縮(用WINZIP,、WINRAR…依次壓迫,,嘿嘿!)教程,。大言不慚的說,,看通本文,你完全可以“不經(jīng)意”間在前輩或是后生賣弄一下DEBUG,,很有成就感的,,試試看!那么――這個接下來呢,?―― Here we go?。ㄩ喿x時看不懂不要緊,,下文必有分解)

  因?yàn)閰R編是通過CPU和內(nèi)存跟硬件對話的,所以我們不得不先了解一下CPU和內(nèi)存:(關(guān)于數(shù)的進(jìn)制問題在此不提)

 ?。茫校帐强梢詧?zhí)行電腦所有算術(shù)╱邏輯運(yùn)算與基本 I/O 控制功能的一塊芯片,。一種匯編語言只能用于特定的CPU。也就是說,,不同的CPU其匯編語言的指令語法亦不相同,。個人電腦由1981年推出至今,其CPU發(fā)展過程為:8086→80286→80386→80486→PENTIUM →……,,還有AMD,、CYRIX等旁支。后面兼容前面CPU的功能,,只不過多了些指令(如多能奔騰的MMX指令集),、增大了寄存器(如386的32位EAX)、增多了寄存器(如486的FS),。為確保匯編程序可以適用于各種機(jī)型,,所以推薦使用8086匯編語言,其兼容性最佳,。本文所提均為8086匯編語言,。寄存器(Register)是CPU內(nèi)部的元件,所以在寄存器之間的數(shù)據(jù)傳送非???。用途:1.可將寄存器內(nèi)的數(shù)據(jù)執(zhí)行算術(shù)及邏輯運(yùn)算。2.存于寄存器內(nèi)的地址可用來指向內(nèi)存的某個位置,,即尋址,。3.可以用來讀寫數(shù)據(jù)到電腦的周邊設(shè)備。8086 有8個8位數(shù)據(jù)寄存器,,這些8位寄存器可分別組成16位寄存器:AH&AL=AX:累加寄存器,,常用于運(yùn)算;BH&BL=BX:基址寄存器,,常用于地址索引,;CH&CL=CX:計數(shù)寄存器,常用于計數(shù),;DH&DL=DX:數(shù)據(jù)寄存器,,常用于數(shù)據(jù)傳遞。為了運(yùn)用所有的內(nèi)存空間,,8086設(shè)定了四個段寄存器,,專門用來保存段地址:CS(Code Segment):代碼段寄存器;DS(Data Segment):數(shù)據(jù)段寄存器,;SS(Stack Segment):堆棧段寄存器,;ES(Extra Segment):附加段寄存器。當(dāng)一個程序要執(zhí)行時,,就要決定程序代碼,、數(shù)據(jù)和堆棧各要用到內(nèi)存的哪些位置,通過設(shè)定段寄存器 CS,,DS,,SS 來指向這些起始位置。通常是將DS固定,,而根據(jù)需要修改CS,。所以,程序可以在可尋址空間小于64K的情況下被寫成任意大小,。 所以,,程序和其數(shù)據(jù)組合起來的大小,限制在DS 所指的64K內(nèi),,這就是COM文件不得大于64K的原因,。8086以內(nèi)存做為戰(zhàn)場,用寄存器做為軍事基地,,以加速工作,。除了前面所提的寄存器外,還有一些特殊功能的寄存器:IP(Intruction Pointer):指令指針寄存器,,與CS配合使用,,可跟蹤程序的執(zhí)行過程;SP(Stack Pointer):堆棧指針,,與SS配合使用,,可指向目前的堆棧位置。BP(Base Pointer):基址指針寄存器,,可用作SS的一個相對基址位置,;SI(Source Index):源變址寄存器可用來存放相對于DS段之源變址指針;DI(Destination Index):目的變址寄存器,,可用來存放相對于 ES 段之目的變址指針,。還有一個標(biāo)志寄存器FR(Flag Register),有九個有意義的標(biāo)志,將在下文用到時詳細(xì)說明,。

  內(nèi)存是電腦運(yùn)作中的關(guān)鍵部分,,也是電腦在工作中儲存信息的地方。內(nèi)存組織有許多可存放數(shù)值的儲存位置,,叫“地址”,。8086地址總線有20位,所以CPU擁有達(dá)1M的尋址空間,,這也是DOS的有效控制范圍,,而8086能做的運(yùn)算僅限于處理16位數(shù)據(jù),,即只有0到64K,所以,,必須用分段尋址才能控制整個內(nèi)存地址,。完整的20位地址可分成兩部份:1.段基址(Segment):16位二進(jìn)制數(shù)后面加上四個二進(jìn)制0,即一個16進(jìn)制0,,變成20位二進(jìn)制數(shù),,可設(shè)定1M中任何一個64K段,通常記做16位二進(jìn)制數(shù),;2.偏移量(Offset):直接使用16位二進(jìn)制數(shù),,指向段基址中的任何一個地址。如:2222(段基址):3333(偏移量),,其實(shí)際的20位地址值為:25553,。除了上述營養(yǎng)要充分吸收外,你還要知道什么是DOS,、BIOS功能調(diào)用,,簡單的說,功能調(diào)用類似于WIN95 API,,相當(dāng)于子程序,。匯編寫程序已經(jīng)夠要命了,如果不用MS,、IBM的子程序,,這日子真是沒法過了(關(guān)于功能調(diào)用詳見《電腦愛好者》98年11期)。

  編寫匯編語言有兩種主要的方法:1.使用MASM或TASM等編譯器;2.使用除錯程序DEBUG.COM。DEBUG其實(shí)并不能算是一個編譯器,,它的主要用途在于除錯,即修正匯編程序中的錯誤,。不過,也可以用來寫短的匯編程序,,尤其對初學(xué)者而言,,DEBUG 更是最佳的入門工具。因?yàn)镈EBUG操作容易:只要鍵入DEBUG回車,,A回車即可進(jìn)行匯編,,過程簡單,而使用編譯器時,,必須用到文本編輯器,、編譯器本身、LINK以及EXE2BIN等程序,其中每一個程序都必須用到一系列相當(dāng)復(fù)雜的命令才能工作,,而且用編譯器處理源程序,,必須加入許多與指令語句無關(guān)的指示性語句,以供編譯器識別,,使用 DEBUG 可以避免一開始就碰到許多難以理解的程序行,。DEBUG 除了能夠匯編程序之外,還可用來檢查和修改內(nèi)存位置,、載入儲存和執(zhí)行程序、以及檢查和修改寄存器,,換句話說,,DEBUG是為了讓我們接觸硬件而設(shè)計的。(8086常用指令用法將在每個匯編程序中講解,,限于篇幅,,不可能將所有指令列出)。

  DEBUG的的A命令可以匯編出簡單的COM文件,,所以DEBUG編寫的程序一定要由地址 100h(COM文件要求)開始才合法,。FOLLOW ME,SETP BY SETP(步步回車):

  輸入 A100 ,; 從DS:100開始匯編
  2.輸入 MOV DL,1 ,; 將數(shù)值 01h 裝入 DL 寄存器
  3.輸入 MOV AH,2 ; 將數(shù)值 02h 裝入 DL 寄存器
  4.輸入 INT 21 ,; 調(diào)用DOS 21號中斷2號功能,,用來逐個顯示裝入DL的字符
  5.輸入 INT 20 ; 調(diào)用DOS 20號中斷,,終止程序,,將控制權(quán)交回給 DEBUG
  6.請按 Enter 鍵
  7.現(xiàn)在已將匯編語言程序放入內(nèi)存中了,輸入 G(運(yùn)行)
  8.出現(xiàn)結(jié)果:輸出一個符號,。
  ㄖ ←輸出結(jié)果其實(shí)不是它,,因WORD97無法顯示原結(jié)果,故找一贗品將就著,。
  Program terminated normally

  我們可以用U命令將十六進(jìn)制的機(jī)器碼反匯編(Unassemble)成匯編指令,。你將發(fā)現(xiàn)每一行右邊的匯編指令就是被匯編成相應(yīng)的機(jī)器碼,而8086實(shí)際上就是以機(jī)器碼來執(zhí)行程序,。
  1.輸入 U100,106
  1FED:0100 B201 MOV DL,01
  1FED:0102 B402 MOV AH,02
  1FED:0104 CD21 INT 21
  1FED:0106 CD20 INT 20
  DEBUG可以用R命令來查看,、改變寄存器內(nèi)容。CS:IP寄存器,,保存了將執(zhí)行指令地址,。
  1.輸入R
  AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
  DS=1FED ES=1FED SS=1FED CS=1FED IP=0100 NV UP EI PL NZ NA PO NC
  1FED:0100 B201 MOV DL,01

  當(dāng)程序由DS:100開始執(zhí)行,那么終止程序時,DEBUG會自動將IP內(nèi)容重新設(shè)定為100,。當(dāng)你要將此程序做成一個獨(dú)立的可執(zhí)行文件,,則可以用N命令對該程序命名。但一定要為COM文件,,否則無法以DEBUG載入,。
  輸入N SMILE.COM ;我們得告訴DEBUG程序長度:程序從100開始到106,,故占用7
 ?。蛔止?jié),。我們利用BX存放長度值高位部分,,而以CX存放低位部分。
  2.輸入RBX ,;查看 BX 寄存器的內(nèi)容,,本程序只有7個字節(jié),故本步可省略
  3.輸入 RCX  ,;查看 CX 寄存器的內(nèi)容
  4.輸入 7  ,;程序的字節(jié)數(shù)
  5.輸入 W ;用W命令將該程序?qū)懭耄╓rite)磁盤中

  修行至此,,我們便可以真正接觸8086匯編指令了,。 當(dāng)我們寫匯編語言程序的時候,通常不會直接將機(jī)器碼放入內(nèi)存中,,而是打入一串助記符號(Mnemonic Symbols),,這些符號比十六進(jìn)制機(jī)器碼更容易記住,此之謂匯編指令,。助記符號,告訴CPU應(yīng)執(zhí)行何種運(yùn)算,。 也就是說,,助憶符號所構(gòu)成的匯編語言是為人設(shè)計的,而機(jī)器語言是對PC設(shè)計的,。

  現(xiàn)在,,我們再來剖析一個可以將所有ASCII碼顯示出來的程序。
  1. 輸入 DEBUG
  2. 輸入 A100
  3.輸入 MOV CX,0100 ,;裝入循環(huán)次數(shù)
  MOV DL,00 ,;裝入第一個ASCII碼,隨后每次循環(huán)裝入新碼
  MOV AH,02
  INT 21
  INC DL ,;INC:遞增指令,,每次將數(shù)據(jù)寄存器 DL 內(nèi)的數(shù)值加 1
  LOOP 0105 ,;LOOP:循環(huán)指令,每執(zhí)行一次LOOP,,CX值減1,,并跳
  ,;到循環(huán)的起始地址105,,直到CX為0,循環(huán)停止
  INT 20
  4.輸入 G即可顯示所有ASCII碼
 
  當(dāng)我們想任意顯示字符串,,如:UNDERSTAND,?,則可以使用DOS21H號中斷9H號功能,。輸入下行程序,存盤并執(zhí)行看看:
  1.輸入 A100
   MOV DX,109 ,;DS:DX = 字符串的起始地址
   MOV AH,9 ;DOS的09h功能調(diào)用
  INT 21 ,;字符串輸出
  INT 20
  DB ‘UNDERSTAND,?$‘,;定義字符串

  在匯編語言中,,有兩種不同的指令:1.正規(guī)指令:如 MOV 等,,是屬于CPU的指令,,用來告訴CPU在程序執(zhí)行時應(yīng)做些什么,,所以它會以運(yùn)算碼(OP-code)的方式存入內(nèi)存中,;2.偽指令:如DB等,是屬于DEBUG等編譯器的指令,,用來告訴編譯器在編譯時應(yīng)做些什么。DB(Define Byte)指令用來告訴DEBUG 將單引號內(nèi)的所有ASCII 碼放入內(nèi)存中,。使用 9H 功能的字符串必須以$結(jié)尾,。用D命令可用來查看DB偽指令將那些內(nèi)容放入內(nèi)存。
  6.輸入 D100
  1975:0100 BA 09 01 B4 09 CD 21 CD-20 75 6E 64 65 72 73 74 ......!. underst
  1975:0110 61 6E 64 24 8B 46 F8 89-45 04 8B 46 34 00 64 19 and$.F..E..F4.d.
  1975:0120 89 45 02 33 C0 5E 5F C9-C3 00 C8 04 00 00 57 56 .E.3.^_.......WV
  1975:0130 6B F8 0E 81 C7 FE 53 8B-DF 8B C2 E8 32 FE 0B C0 k.....S.....2...
  1975:0140 74 05 33 C0 99 EB 17 8B-45 0C E8 D4 97 8B F0 89 t.3.....E.......
  1975:0150 56 FE 0B D0 74 EC 8B 45-08 03 C6 8B 56 FE 5E 5F V...t..E....V.^_
  1975:0160 C9 C3 C8 02 00 00 6B D8-0E 81 C3 FE 53 89 5E FE ......k.....S.^.
  1975:0170 8B C2 E8 FB FD 0B C0 75-09 8B 5E FE 8B 47 0C E8 .......u..^..G..

  現(xiàn)在,,我們來剖析另一個程序:由鍵盤輸入任意字符串,然后顯示出來,。db 20指示DEBUG保留20h個未用的內(nèi)存空間供緩沖區(qū)使用,。
  輸入A100
   MOV DX,0116 ;DS:DX = 緩沖區(qū)地址,由DB偽指令確定緩沖區(qū)地址
  MOV AH,0A ,;0Ah 號功能調(diào)用
  INT 21 ,;鍵盤輸入緩沖區(qū)
  MOV DL,0A ;由于功能Ah在每個字符串最后加一個歸位碼(0Dh由 Enter
  MOV AH,02 ,;產(chǎn)生),,使光標(biāo)自動回到輸入行的最前端,為了使新輸出的
  INT 21 ,;字符串不會蓋掉原來輸入的字符串,,所以利用功能2h加一
  ,;個換行碼(OAh),,使得光標(biāo)移到下一行的的最前端。
  MOV DX,0118 ,;裝入字符串的起始位置
  MOV AH,09 ,;9h功能遇到$符號才會停止輸出,故字符串最后必須加上
  INT 21 ,;$,,否則9h功能會繼續(xù)將內(nèi)存中的無用數(shù)據(jù)胡亂顯示出來
  INT 20
  DB 20 ,;定義緩沖區(qū)
  送你一句話:學(xué)匯編切忌心浮氣燥,。

  客套話就不講了。工欲善其事,,必先利其器,。與其說DEBUG 是編譯器,倒不如說它是“直譯器”,,DEBUG的A命令只可將一行匯編指令轉(zhuǎn)成機(jī)器語言,,且立刻執(zhí)行。真正編譯器(MASM)的運(yùn)作是利用文本編輯器(EDIT等)將匯編指令建成一個獨(dú)立且附加名為.ASM的文本文件,,稱源程序,。它是MASM 程序的輸入部分。MASM將輸入的ASM文件,,編譯成.OBJ文件,,稱為目標(biāo)程序。OBJ文件僅包含有關(guān)程序各部份要載入何處及如何與其他程序合并的信息,,無法直接載入內(nèi)存執(zhí)行,。鏈結(jié)程序LINK則可將OBJ文件轉(zhuǎn)換成可載入內(nèi)存執(zhí)行(EXEcute)的EXE文件。還可以用EXE2BIN,,將符合條件的EXE文件轉(zhuǎn)成COM文件(COM 文件不但占用的內(nèi)存最少,,而且運(yùn)行速度最快),。
  下面我們用MASM寫一個與用DEBUG寫的第一個程序功能一樣的程序。
  用EDIT編輯一個SMILE.ASM的源程序文件,。
  源程序 DEBUG 程序
  prognam segment
  assume cs:prognam
  org 100h A100
  mov dl,1 mov dl,1
  mov ah,2 mov ah,2
  int 21h int 21
  int 20h int 20
  prognam ends
  end

  比較一下:1.因?yàn)镸ASM會將所有的數(shù)值假設(shè)為十進(jìn)制,,而DEBUG則只使用十六進(jìn)制,所以在源程序中,,我們必須在有關(guān)數(shù)字后加上代表進(jìn)制的字母,,如H代表十六進(jìn)制,D代表十進(jìn)制,。若是以字母開頭的十六進(jìn)制數(shù)字,,還必須在字母前加個0,以表示它是數(shù),,如0AH,。2.源程序增加五行敘述:prognam segment 與 prognam ends 是成對的,用來告訴 MASM 及LINK,,此程序?qū)⒎旁谝粋€稱為PROGNAM(PROGram NAMe)的程序段內(nèi),,其中段名(PROGNAM)可以任取,但其位置必須固定,。assume cs:prognam 必須在程序的開頭,,用來告訴編譯器此程序所在段的位置放在CS寄存器中。end用來告訴MASM,,程序到此結(jié)束, ORG 100H作用相當(dāng)于DEBUG的A100,從偏移量100開始匯編,。COM 文件的所有源程序都必須包含這五行,,且必須依相同的次序及位置出現(xiàn),這點(diǎn)東西記下就行,,千篇一律,。接著,我們用MASM編譯SMILE.ASM,。
  輸入 MASM SMILE ←不用打入附加名.ASM,。
  Microsoft (R) Macro Assembler Version 5.10
  Copyright (C) Microsoft Corp 1981, 1988. All rights reserved.
  Object filename [SMILE.OBJ]: ←是否改動輸出OBJ文件名,如不改就ENTER
  Source listing [NUL.LST]: ← 是否需要列表文件(LST),,不需要就ENTER
  Cross-reference [NUL.CRF]: ←是否需要對照文件(CRF),,不需要則ENTER
  50162 + 403867 Bytes symbol space free
  0 Warning Errors ←警告錯誤,表示編譯器對某些語句不理解,,通常是輸入錯誤,。
  0 Severe Errors ←嚴(yán)重錯誤,會造成程序無法執(zhí)行,,通常是語法結(jié)構(gòu)錯誤,。

  如果沒有一個錯誤存在,,即可生成OBJ文件。OBJ中包含的是編譯后的二進(jìn)制結(jié)果,,它還無法被 DOS載入內(nèi)存中加以執(zhí)行,,必須加以鏈結(jié)(Linking)。以LINK將OBJ文件(SMILE.OBJ)鏈結(jié)成 EXE 文件(SMILE.EXE)時,,,。
  1.輸入 LINK SMILE ←不用附加名OBJ
  Microsoft (R) Overlay Linker Version 3.64
  Copyright (C) Microsoft Corp 1981, 1988. All rights reserved.
  Run File [SMILE.EXE]: ← 是否改動輸出EXE文件名,如不改就ENTER
  List File [NUL.MAP]: ← 是否需要列表文件(MAP),,不需要則ENTER
  Libraries [.LIB]: ←是否需要庫文件,,要就鍵入文件名,不要則ENTER
  LINK : warning L4021: no stack segment← 由于COM文件不使用堆棧段,,所以錯誤信息
  ←"no stack segment"并不影響程序正常執(zhí)行

  至此已經(jīng)生成EXE文件,,我們還須使用EXE2BIN 將EXE文件(SMILE.EXE),轉(zhuǎn)換成COM文件(SMILE.COM),。輸入EXE2BIN SMILE產(chǎn)生 BIN 文件(SMILE.BIN),。其實(shí) BIN 文件與 COM 文件是完全相同的,但由于DOS只認(rèn)COM,、EXE及BAT文件,,所以BIN文件無法被正確執(zhí)行,改名或直接輸入 EXE2BIN SMILE SMILE.COM即可?,F(xiàn)在,,磁盤上應(yīng)該有 SMILE.COM 文件了,你只要在提示符號C:>下,,直接輸入文件名稱 SMILE ,,就可以執(zhí)行這個程序了。

  你是否覺得用編譯器產(chǎn)生程序的方法,,比 DEBUG 麻煩多了,!以小程序而言,的確是如此,,但對于較大的程序,,你就會發(fā)現(xiàn)其優(yōu)點(diǎn)了。我們再將ASCII程序以編譯器方式再做一次,,看看有無差異,。首先,用EDIT.COM建立 ASCII.ASM 文件,。
  prognam segment ;定義段
  assume cs:prognam ;把上面定義段的段基址放入 CS
  mov cx,100h ; 裝入循環(huán)次數(shù)
  mov dl,0 ; 裝入第一個ASCII碼,,隨后每次循環(huán)裝入新碼
  next: mov ah,2
   int 21h
   inc dl ;INC:遞增指令,每次將數(shù)據(jù)寄存器 DL 內(nèi)的數(shù)值加 1
  loop next ; 循環(huán)指令,,執(zhí)行一次,,CX減1,,直到CX為0,循環(huán)停止
  int 20h
   prognam ends ;段終止
  end ;匯編終止
  在匯編語言的源程序中,,每一個程序行都包含三項(xiàng)元素:
    start: mov dl,1 ,;裝入第一個ASCII碼,隨后每次循環(huán)裝入新碼
    標(biāo)識符 表達(dá)式 注解

  在原始文件中加上注解可使程序更易理解,,便于以后參考,。每行注解以“;”與程序行分離,。編譯器對注解不予理會,,注解的數(shù)據(jù)不會出現(xiàn)在OBJ、EXE或COM文件中,。由于我們在寫源程序時,,并不知道每一程序行的地址,所以必須以符號名稱來代表相對地址,,稱為“標(biāo)識符”,。我們通常在適當(dāng)行的適當(dāng)位置上,鍵入標(biāo)識符,。標(biāo)識符(label)最長可達(dá)31 個字節(jié),,因此我們在程序中,盡量以簡潔的文字做為標(biāo)識符?,F(xiàn)在,,你可以將此ASCII.ASM 文件編譯成 ASCII.COM 了。1.MASM ASCII,,2.LINK ASCII,,3.EXE2BIN ASCII ASCII.COM。

  注意:當(dāng)你以編譯器匯編你設(shè)計的程序時,,常會發(fā)生打字錯誤、標(biāo)識符名稱拼錯,、十六進(jìn)制數(shù)少了h,、邏輯錯誤等。匯編老手常給新人的忠告是:最好料到自己所寫的程序一定會有些錯誤(別人告訴我的),;如果第一次執(zhí)行程序后,,就得到期望的結(jié)果,你最好還是在檢查一遍,,因?yàn)樗赡苁清e的,。原則上,只要大體的邏輯架構(gòu)正確,,查找程序中錯誤的過程,,與寫程序本身相比甚至更有意思,。寫大程序時,最好能分成許多模塊,,如此可使程序本身的目的較單純,,易于撰寫與查錯,另外也可讓程序中不同部份之間的界限較清楚,,節(jié)省編譯的時間,。如果讀程序有讀不懂的地方最好用紙筆記下有關(guān)寄存器、內(nèi)存等內(nèi)容,,在紙上慢慢比劃,,就豁然開朗了。   下面我們將寫一個能從鍵盤取得一個十進(jìn)制的數(shù)值,,并將其轉(zhuǎn)換成十六進(jìn)制數(shù)值而顯示于屏幕上的“大程序”,。前言:要讓8086執(zhí)行這樣的功能,我們必須先將此問題分解成一連串的步驟,,稱為程序規(guī)劃,。首先,以流程圖的方式,,來確保整個程序在邏輯上沒有問題(不用說了吧,!什么語言都要有此步驟)。這種模塊化的規(guī)劃方式,,稱之為“由上而下的程序規(guī)劃”,。而在真正寫程序時,卻是從最小的單位模塊(子程序)開始,,當(dāng)每個模塊都完成之后,,再合并成大程序;這種大處著眼,,小處著手的方式稱為“由下而上的程序設(shè)計”,。

  我們的第一個模塊是BINIHEX,其主要用途是從8086的BX寄存器中取出二進(jìn)制數(shù),,并以十六進(jìn)制方式顯示在屏幕上,。注意:子程序如不能獨(dú)立運(yùn)行,實(shí)屬正常,。
   binihex segment
   assume cs:binihex
  mov ch,4 ;記錄轉(zhuǎn)換后的十六進(jìn)制位數(shù)(四位)
  rotate: mov cl,4 ;利用CL當(dāng)計數(shù)器,,記錄寄存器數(shù)位移動次數(shù)
  rol bx,cl ;循環(huán)寄存器BX的內(nèi)容,以便依序處理4個十六進(jìn)制數(shù)
  mov al,bl ;把bx低八位bl內(nèi)數(shù)據(jù)轉(zhuǎn)移至al
  and al,0fh ;把無用位清零
  add al,30h ;把AL內(nèi)數(shù)據(jù)加30H,,并存入al
  cmp al,3ah ;與3ah比較
  jl printit ;小于3ah則轉(zhuǎn)移
  add al,7h ;把AL內(nèi)數(shù)據(jù)加30H,,并存入al
  printit:mov dl,al ;把ASCII碼裝入DL
  mov ah,2
   int 21h
   dec ch ;ch減一,減到零時,,零標(biāo)志置1
  jnz rotate ;JNZ:當(dāng)零標(biāo)志未置1,,則跳到指定地址,。即:不等,則轉(zhuǎn)移
  int 20h ;從子程序退回主程序
  binihex ends
   end

  利用循環(huán)左移指令ROL循環(huán)寄存器BX(BX內(nèi)容將由第二個子程序提供)的內(nèi)容,,以便依序處理4個十六進(jìn)制數(shù):1. 利用CL當(dāng)計數(shù)器,,記錄寄存器移位的次數(shù)。2.將BX的第一個十六進(jìn)制值移到最右邊,。利用 AND (邏輯“與”運(yùn)算:對應(yīng)位都為1時,,其結(jié)果為1,其余情況為零)把不要的部份清零,,得到結(jié)果:先將BL值存入AL中,,再利用AND以0Fh(00001111)將AL的左邊四位清零。由于0到9的ASCII碼為30h到39h,,而A到F之ASCII碼為41h到46h,,間斷了7h,所以得到結(jié)果:若AL之內(nèi)容小于3Ah,,則AL值只加30h,,否則AL再加7h。ADD指令會將兩個表達(dá)式相加,,其結(jié)果存于左邊表達(dá)式內(nèi),。標(biāo)志寄存器(Flag Register)是一個單獨(dú)的十六位寄存器,有9個標(biāo)志位,,某些匯編指令(大部份是涉及比較,、算術(shù)或邏輯運(yùn)算的指令)執(zhí)行時,會將相關(guān)標(biāo)志位置1或清0,, 常碰到的標(biāo)志位有零標(biāo)志(ZF),、符號標(biāo)志(SF)、溢出標(biāo)志(OF)和進(jìn)位標(biāo)志(CF),。 標(biāo)志位保存了某個指令執(zhí)行后對它的影響,,可用其他相關(guān)指令,查出標(biāo)志的狀態(tài),,根據(jù)狀態(tài)產(chǎn)生動作,。CMP指令很像減法,是將兩個表達(dá)式的值相減,,但寄存器或內(nèi)存的內(nèi)容并未改變,只是相對的標(biāo)志位發(fā)生改變而已:若 AL 值小于 3Ah,,則正負(fù)號標(biāo)志位會置0,,反之則置1。 JL指令可解釋為:小于就轉(zhuǎn)移到指定位置,,大于,、等于則向下執(zhí)行,。CMP和JG 、JL等條件轉(zhuǎn)移指令一起使用,,可以形成程序的分支結(jié)構(gòu),,是寫匯編程序常用技巧。

  第二個模塊DECIBIN 用來接收鍵盤打入的十進(jìn)制數(shù),,并將它轉(zhuǎn)換成二進(jìn)制數(shù)放于BX 寄存器中,,供模塊1 BINIHEX使用。
  decibin segment
  assume cs:decibin
  mov bx,0 ;BX清零
  newchar:mov ah,1 ;
  int 21h ;讀一個鍵盤輸入符號入al,,并顯示
  sub al,30h ;al減去30H,,結(jié)果存于al中,完成ASCII碼轉(zhuǎn)二進(jìn)制碼
  jl exit ;小于零則轉(zhuǎn)移
  cmp al,9d
   jg exit ;左>右則轉(zhuǎn)移
  cbw ;8位al轉(zhuǎn)換成16位ax
  xchg ax,bx ;互換ax和bx內(nèi)數(shù)據(jù)
  mov cx,10d ;十進(jìn)制數(shù)10入cx
  mul cx ;表達(dá)式的值與ax內(nèi)容相乘,,并將結(jié)果存于ax
  xchg ax,bx
   add bx,ax
   jmp newchar ;無條件轉(zhuǎn)移
  exit: int 20 ;回主程序
  decibin ends
   end
  CBW 實(shí)際結(jié)果是:若AL中的值為正,,則AH填入00h;反之,,則AH填入FFh,。XCHG常用于需要暫時保留某個寄存器中的內(nèi)容時。
  當(dāng)然,,還得一個子程序(CRLF)使后顯示的十六進(jìn)制數(shù)不會蓋掉先輸入的十進(jìn)制數(shù),。
  crlf segment
  assume cs:crlf
  mov dl,0dh ;回車的ASCII碼0DH入DL
  mov ah,2
   int 21h
   mov dl,0ah ;換行的ASSII碼0AH入AH
  mov ah,2
   int 21h
   int 20 ;回主程序
  crlf ends
  end

  現(xiàn)在我們就可以將BINIHEX、DECIBIN及CRLF等模塊合并成一個大程序了,。首先,,我們要將這三個模塊子程序略加改動。然后,,再寫一段程序來調(diào)用每一個子程序,。
  crlf proc near;
  mov dl,0dh
  mov ah,2
  int 21h
  mov dl,0ah
  mov ah,2
  int 21h
  ret
  crlf endp

  類似SEGMENT與ENDS的偽指令,,PROC與ENDP也是成對出現(xiàn),,用來識別并定義一個程序。其實(shí),,PROC 真正的作用只是告訴編譯器:所調(diào)用的程序是屬于近程(NEAR)或遠(yuǎn)程(FAR),。 一般的程序是由 DEBUG 直接調(diào)用的,所以用 INT 20 返回,,用 CALL 指令所調(diào)用的程序則改用返回指令RET,RET會把控制權(quán)轉(zhuǎn)移到棧頂所指的地址,,而該地址是由調(diào)用此程序的 CALL指令所放入的。
  各模塊都搞定了,,然后我們把子程序組合起來就大功告成
  decihex segment ;主程序
  assume cs:decihex
  org 100h
  mov cx,4 ;循環(huán)次數(shù)入cx,;由于子程序要用到cx,故子程序要將cx入棧
  repeat: call decibin;調(diào)用十進(jìn)制轉(zhuǎn)二進(jìn)制子程序
  call crlf ;調(diào)用添加回、換行符子程序
  call binihex ;調(diào)用二進(jìn)制轉(zhuǎn)十六進(jìn)制并顯示子程序
  call crlf
  loop repeat ;循環(huán)4次,,可連續(xù)運(yùn)算4次
  mov ah,4ch ; 調(diào)用DOS21號中斷4c號功能,,退出程序,作用跟INT 20H
  int 21H ; 一樣,,但適用面更廣,,INT20H退不出時,試一下它
  decibin proc near push cx ;將cx壓入堆棧,,;
  ┇ exit: pop cx ;將cx還原; retdecibin endp binihex proc near push cx
  ┇ pop cx retbinihex endp crlf proc near
   push cx
  ┇ pop cx retcrlf endpdecihex ends end

  CALL指令用來調(diào)用子程序,,并將控制權(quán)轉(zhuǎn)移到子程序地址,同時將CALL的下行一指令地址定為返回地址,,并壓入堆棧中,。CALL 可分為近程(NEAR)及遠(yuǎn)程(FAR)兩種:1.NEAR:IP的內(nèi)容被壓入堆棧中,用于程序與程序在同一段中,。2.FAR:CS ,、IP寄存器的內(nèi)容依次壓入堆棧中,用于程序與程序在不同段中。PUSH,、POP又是一對指令用于將寄存器內(nèi)容壓入,、彈出,用來保護(hù)寄存器數(shù)據(jù),,子程序調(diào)用中運(yùn)用較多,。堆棧指針有個“后進(jìn)先出”原則,像PUSH AX,,PUSH BX…POP BX,,POP AX這樣才能作到保護(hù)數(shù)據(jù)絲毫不差。

  匯編語言超濃縮教程到這要告一段落了,,希望能奠定你獨(dú)立設(shè)計的基礎(chǔ),。而更多更好的技巧則全依賴你平時的積累了。祝你成功,!

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn),。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多