久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

匯編語言入門教程(這一篇足矣)

匯編語言是一種最低級、最古老、不具有移植性的編程語言,它能夠直接訪問計算機(jī)硬件,所以執(zhí)行效率極高,占用資源極少,想學(xué)習(xí)匯編語言的朋友不妨閱讀下本教程

匯編語言是一種最低級、最古老、不具有移植性的編程語言,它能夠直接訪問計算機(jī)硬件,所以執(zhí)行效率極高,占用資源極少,一般用于嵌入式設(shè)備、驅(qū)動程序、實(shí)時應(yīng)用、核心算法等。

匯編語言的缺點(diǎn)是開發(fā)周期特別長,實(shí)現(xiàn)一個簡單的功能都非常麻煩,已經(jīng)很少用來編寫應(yīng)用程序了。

1 本講座以匯編初學(xué)者或?qū)R編一點(diǎn)也不了解的讀者為對象,匯編高手不屬于該范圍,但強(qiáng)烈建議高手指導(dǎo)并增補(bǔ)、修改本文。

2 任何讀者可以跟此貼,提出疑問,或解答其中的問題,但對于所有跟貼,水貼、內(nèi)容有錯、毫不相干貼將直接刪除,有意義的貼可能會合并到下一講的內(nèi)容中,合并后也將刪除,請跟貼者諒解。同時按學(xué)習(xí)進(jìn)步,請?zhí)釂栒咧鸩教幔灰覜]開口,你就問怎么編個病毒的問題。

3 借以拋磚引玉,但不希望大家只朝我扔磚頭,希望大家踴躍思考,使之完善。

大家坐好了,。不要,不要,不要,男女同學(xué)不要相互,女同學(xué)不要對我….

1 匯編需要什么工具和程序,到哪里下載?

目前階段,匯編程序僅需要兩個程序就夠了: masm.exe,link.exe。前者是編譯程序,后者是鏈接程序。

另外,為了驗證和調(diào)試程序,還需要一個程序debug.exe,該程序由windows本身就提供,所以就不提供下載地址了。
將二者下載后,放到某一個目錄中(任意目錄都可以),考慮到很多命令需要通過鍵盤敲入,所以建議你不要把文件放入到長文件名目錄、中文目錄或很深的目錄中。比如你可以建一個“D:\Masm”目錄,并建議此后的程序都放這個目錄,此后稱這個目錄為匯編目錄。

2 學(xué)習(xí)匯編需要有哪些編程方面的知識。

沒有任何編程方面的知識,學(xué)習(xí)此語言等于緣木求魚,所以請放棄學(xué)習(xí)的想法。一般來說至少要知道如下幾點(diǎn):

*)程序的運(yùn)行邏輯結(jié)構(gòu)有順序(按語句依次執(zhí)行)、分支結(jié)構(gòu)(IF…THEN…ELSE…),循環(huán)結(jié)構(gòu)(FOR…NEXT)三種結(jié)構(gòu)。

*)知道什么是子程序,什么是調(diào)用。

*)匯編程序員的視角。不同編程視角編程要求是不一樣的。比如刪除文件,

>>用戶的視角是找到“刪除”按鈕或菜單,然后單擊一下即可。

>>高級程序員的視角是知道刪除的文件,并發(fā)出刪除命令。這些通過API實(shí)現(xiàn)。

>>匯編程員的視角是得到要刪除的文件名,找到該文件所在位置,通過調(diào)用刪除“中斷命令”進(jìn)行刪除。

>>操作系統(tǒng)開發(fā)人員的視角則是接到刪除命令后,先找到系統(tǒng)根目錄區(qū),由根目錄區(qū)的鏈接依次找到子目錄區(qū),直到找到要刪除的文件,然后按照操作系統(tǒng)刪除文件的規(guī)則對該文件名進(jìn)行修改。比如DOS,只把第一個字符改成"?"。

按程序語句等價的角度看,一行VB的打印語句,用匯編實(shí)現(xiàn)大約需要一百二十多行。知道匯編語言的視角后就要知道,前面的道路是坎坷的,沒有耐心是不行的。想通過幾分鐘幾行程序就完成很復(fù)雜的操作不是件容易的事。

3 學(xué)匯編有什么用?

匯編產(chǎn)生于DOS時代或更早,而現(xiàn)在是Windows時代,所以可能遺憾地說:盡管還有批牛人在用匯編開發(fā)核心級程序,但我們幾乎沒什么用,除了必要時間能拿來分析一兩個程序的部分代碼之外,別的也就沒干什么用了。并且并不是所有的匯編命令都能在windows下使用。而泛泛地追求“時髦”而學(xué)本語言,最后的結(jié)果是損了夫人又折兵。所以學(xué)之前你要考慮好。我勸那些為了當(dāng)“黑客”而學(xué)匯編的人就此止步。

第零講 預(yù)備知識

1 一個匯編程序的編譯過程是怎么樣的。

1)首先你需要找一個編輯器,編輯器用任何“純文本”編輯器都可以。比如記事本。編好以后保存到匯編目錄中。擴(kuò)展名為asm,比如myfirst.asm。但這里建議你找一個能顯示出當(dāng)前行的編譯器。這樣出錯后排錯很容易。
2)然后在DOS下進(jìn)入D:\Masm目錄中,輸入“masm myfirst.asm",如果有錯系統(tǒng)會提示出錯的行位置和出錯原因。
3)然后再輸入“l(fā)ink myfirst.obj”,即可看到當(dāng)前目錄下有一個myfirst.exe程序。

2 宏匯編和匯編有什么區(qū)別嗎?

二者的區(qū)別在于前者提供宏,后者不提供。后者已找不到了,所以你可以認(rèn)為二者沒有區(qū)別。

3 機(jī)器語言、匯編語言、高級語言的關(guān)系

最早的計算機(jī)采用機(jī)器語言,這種語言直接用二進(jìn)制數(shù)表示,通過直接輸入二進(jìn)制數(shù),插拔電路板等實(shí)現(xiàn),這種“編程”很容易出錯,每個命令都是通過查命令表實(shí)現(xiàn),既然是通過“查表”實(shí)現(xiàn)的,那當(dāng)然也可以讓計算機(jī)來代替人查表實(shí)現(xiàn)了。于是就產(chǎn)生了匯編語言,所以不管別人怎么定義機(jī)、匯語言,我就認(rèn)為,二者是等價。后來人們發(fā)現(xiàn),用匯編語言編某一功能的時候,連續(xù)一段代碼都是相同或相似,于是就考慮用一句語言來代替這一段匯編語言,于是就產(chǎn)生了高級語言。因此,所有高級語言都能轉(zhuǎn)化成匯編語言,而所以匯編語言又可轉(zhuǎn)化成機(jī)器語言。反之,所有機(jī)器語言可以轉(zhuǎn)成匯編語言(因為二者等價)。但并不是所以匯編語言都能轉(zhuǎn)成高級語言。

4 計算機(jī)的組成

通常都把計算機(jī)定義成五部分:運(yùn)算器、控制器、存儲器、輸入系統(tǒng)、輸出系統(tǒng)。
為了簡單其間,我們?nèi)绱死斫猓哼\(yùn)算器+控制器=CPU。存儲器=內(nèi)存(暫不包括外存,永不包括CACHE)。輸入系統(tǒng)=鍵盤(不包括鼠標(biāo)),輸入系統(tǒng)=顯示器(不包括打印機(jī),繪圖儀)。

5 寄存器和內(nèi)存的區(qū)別

寄存器在CPU中。內(nèi)存在內(nèi)存條中。前者的速度比后者快100倍左右。后面的程序要求每條指定要么沒有內(nèi)存數(shù)據(jù),要么在有一個寄存器的參與下有一個內(nèi)存數(shù)據(jù)。(也就是說,不存在只訪問內(nèi)存的指令)。

6 匯編語言的計數(shù)

與生活中的計數(shù)不一樣,匯編中的計數(shù)是從0開始的。比如16個計數(shù),則是從0~15,而不是生活中的1~16。這一點(diǎn)看起來簡單,真運(yùn)算起來就不是件容易的事了,不信等著瞧。

7 進(jìn)制問題

又與生活中不一樣的地方是進(jìn)制。切記下面的常識:

*)計算機(jī)內(nèi)部存儲都用二進(jìn)制。
*)我們的匯編源程序默認(rèn)都用十進(jìn)制。(除非你指明類型)
*)我們用的調(diào)試程序debug默認(rèn)的都是十六進(jìn)制。(無法指明其他類型)
其中十六進(jìn)制的十六個個位數(shù)依次是:0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F(xiàn)。

8 進(jìn)制轉(zhuǎn)換

一個比較簡單的方法是查表法。

十進(jìn)制 十六進(jìn)制 二進(jìn)制

0 0 0000
1 1 0001
2 2 0010
3 3 0011
4 4 0100
5 5 0101
6 6 0110
7 7 0111
8 8 1000
9 9 1001
10 A 1010
11 B 1011
12 C 1100
13 D 1101
14 E 1110
15 F 1111

好了,結(jié)合6,7,8三條。大家來算一個“題”。某一組數(shù)據(jù)顯示時,每個數(shù)據(jù)占了四個位置,

每行共十六個。問:十六進(jìn)制的13位置在哪里(第幾行,第幾列)。

格式如下:m m m m n n n n o o o o p p p p '注:之所以沒用ABC是怕與上面十六進(jìn)制弄混。
r r r r s s s s t t t t u u u u

第一講 基礎(chǔ)知識

1 訪問內(nèi)存

程序在內(nèi)存中,訪問內(nèi)存是幾乎每一程序都要進(jìn)行的操作,計算機(jī)對內(nèi)存編址是線性的,也就是說是一維的,比如256M的內(nèi)存,地址就應(yīng)該是從0~(256M-1),這個地址稱為物理地址或絕對地址。

1.1 地址表示

但從匯編程序員的角度看,內(nèi)存卻是二維的,要說明一個地址,需要給出兩個值,就象你在平面上指定一點(diǎn)需要說出(X,Y)坐標(biāo)一樣,匯編程序員的內(nèi)存視角也需要兩個“坐標(biāo)”,前一個稱為段地址(Segment),后一個稱為偏移地址(Offset),該地址稱為邏輯地址。
比如“1234:3DF5”就是一個地址。“1F3F:”不是一個地址,因為他只有段地址,沒有編移地址。注意此后的地址都用十六進(jìn)制表示。

1.2 地址計算

前面提到,計算機(jī)編址是一維的,匯編程序員是二維的,那么二者怎么換算呢?由后者到前者的換算方法是,“段地址串”后面加個“0”,然后再加上偏移地址。
比如“1234:3DF5”(十六進(jìn)制的加減運(yùn)算參見相關(guān)資料)
12340 ‘串后加了一個0
3DF5
—–
16135 '注意此串仍然是十六進(jìn)制。
所以,匯編程序員眼中的地址“1234:3DF5”就是物理地址(計算機(jī)編址):16135。
知道了由后者向前者的轉(zhuǎn)換,那么由前者向后者的轉(zhuǎn)換呢?
“不知道”,為什么不知道,繼續(xù)往下看。
1.3 到底哪個地址對。
知道了1.2的地址算法后,我又發(fā)現(xiàn)一個問題:
“1000:6135”的物理地址是多少呢? 10000+6135=16135。
“1001:6125”的物理地址呢? 10010+6125=16135。
……
那么到底哪個對呢?問題的回答是這樣的:假設(shè)我現(xiàn)在讓你按一下“L”鍵,我可以告訴你如下幾種方法中的一種或幾種。1 請按一下“L”鍵; 2請按一下鍵盤上第四行第十個鍵;3 請按一下第十列中的第四個鍵;4 請按一下“K”右邊的鍵;5 按標(biāo)準(zhǔn)指法單擊一下右手無名指。
舉上面的例子也就是說,同一個地址有很多種表示方式,具體用哪一種,要看實(shí)際使用時的情況。但無論用哪種方式,只要能達(dá)到目的即可。(實(shí)際中該問題一般不會受此問題困擾,但初學(xué)時突然想不通)。
1.4 有多少內(nèi)存可以訪問
無論是段地址還是偏移地址都是四位十六進(jìn)制(如果不夠四位,前面補(bǔ)0)。也就是說:總共可以訪問的地址說是:0000:0000~FFFF:FFFF。 總共FFFF0+FFFF+1=10FFF0個地址。也就是不到1M的空間。
記住如下結(jié)論:
*)不管你實(shí)際內(nèi)存有多少,目前我們只能訪問不到1M的空間。
*)而實(shí)際上連這1M也用不完。其中上端的384K的址只能讀不能寫,只能讀,一般稱為ROM。
*)低端的640K可以讀寫。但這640K的低端100多K也不能隨便寫,因此DOS系統(tǒng)使用該區(qū)。
*)原來1024M的內(nèi)存,匯編程序只能使用其中400多K。這段內(nèi)存的容易相當(dāng)于一個普通文檔的大小。不過這就足夠了。

2 DEBUG的使用

先記住以下兩個命令:D命令和Q命令。前者是顯示內(nèi)存內(nèi)容,后者是退出DEBUG命令。
————-以下為抄別的人內(nèi)容—————
DEBUG.EXE程序是專門為分析、研制和開發(fā)匯編語言程序而設(shè)計的一種調(diào)試工具,具有跟蹤程序執(zhí)行、觀察中間運(yùn)行結(jié)果、顯示和修改寄存器或存儲單元內(nèi)容等多種功能。它能使程序設(shè)計人員或用戶觸及到機(jī)器內(nèi)部,因此可以說它是80X86CPU的心靈窗口,也是我們學(xué)習(xí)匯編語言必須掌握的調(diào)試工具。

1)DEBUG程序使用

在DOS提示符下鍵入命令:

C>DEBUG [盤符:][路徑][文件名.EXE][參數(shù)1][參數(shù)2]

這時屏幕上出現(xiàn)DEBUG的提示符“-”,表示系統(tǒng)在DEBUG管理之下,此時可以用DEBUG進(jìn)行程序調(diào)試。若所有選項省略,僅把DEBUG裝入內(nèi)存,可對當(dāng)前內(nèi)存中的內(nèi)容進(jìn)行調(diào)試,或者再用N和L命令,從指定盤上裝入要調(diào)試的程序;若命令行中有文件名,則DOS把DEBUG程序調(diào)入內(nèi)存后,再由DEBUG將指定的文件名裝入內(nèi)存。

2)DEBUG的常用命令

(1)退出命令 Q
格式:Q
功能:退出DEBUG,返回到操作系統(tǒng)。
(2)顯示存儲單元命令 D
格式1:D[起始地址]
格式2:D[起始地址][結(jié)束地址|字節(jié)數(shù)]
功能:格式1從起始地址開始按十六進(jìn)制顯示80H個單元的內(nèi)容,每行16個單元,共8行,每行右邊顯示16個單元的ASCII碼,不可顯示的ASCII碼則顯示“·”。格式2顯示指定范圍內(nèi)存儲單元的內(nèi)容,其他顯示方式與格式1一樣。如果缺省起始地址或地址范圍,則從當(dāng)前的地址開始按格式1顯示。
例如: -D 200 ;表示從DS:0200H開始顯示128個單元內(nèi)容
-D 100 120 ;表示顯示DS:0100-DS:0120單元的內(nèi)容
說明:在DEBUG中,地址表示方式有如下形式:
段寄存器名:相對地址,如:DS:100
段基值:偏移地址(相對地址),如:23A0:1500

————————–小抄結(jié)束——————————–

3 驗證第一節(jié)里的內(nèi)容

運(yùn)行“開始/程序/附件/MS-DOS命令提示符”(這是win2000,win98下自己找吧)
在“_”下輸入D,顯示

-d
1398:0100 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 …………….
1398:0110 00 00 00 00 00 00 00 00-00 00 00 00 34 00 87 13 …………4…
1398:0120 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 …………….
1398:0130 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 …………….
1398:0140 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 …………….
1398:0150 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 …………….
1398:0160 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 …………….
1398:0170 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 …………….
-

我們記下:1398:011C的值是個34。1389:011C的物理地址應(yīng)該是:13A9C。
那么1000:3A9C的物理地址也應(yīng)該是13A9C,他的內(nèi)存也應(yīng)該是34,(因為本來就是一個地址嗎,就象第三行第十列和第十列第三行當(dāng)然應(yīng)該是同一個位置)。
-d 1000:3A9C
1000:3A90 34 00 87 13 4…
1000:3AA0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 …………….
1000:3AB0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 …………….
1000:3AC0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 …………….
1000:3AD0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 …………….
1000:3AE0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 …………….
1000:3AF0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 …………….
1000:3B00 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 …………….
1000:3B10 00 00 00 00 00 00 00 00-00 00 00 00 …………
-
果然如此,同樣你可以驗證:13A9:000C也肯定是指這一個地址,不信試試。

4 DEBUG命令

——————-繼續(xù)小抄—————-
前面已學(xué)過:顯示存儲單元命令 D
再學(xué)一個命令
(1)修改存儲單元命令 E

格式1:E[起始地址] [內(nèi)容表]

格式2:E[地址]

功能:格式1按內(nèi)容表的內(nèi)容修改從起始地址開始的多個存儲單元內(nèi)容,即用內(nèi)容表指定的內(nèi)容來代替存儲單元當(dāng)前內(nèi)容。

例如:—E DS:0100 'VAR' 12 34

表示從DS:0100 為起始單元的連續(xù)五個字節(jié)單元內(nèi)容依次被修改為

'V'、'A'、'R'、12H、34H。

格式2是逐個修改指定地址單元的當(dāng)前內(nèi)容。

如:—E DS:0010

156F:0010 41.5F

其中156F:0010單元原來的值是41H,5FH為輸入的修改值。若只修改一個單元的內(nèi)容,這時按回車鍵即可;若還想繼續(xù)修改下一個單元內(nèi)容,此時應(yīng)按空格鍵,就顯示下一個單元的內(nèi)容,需修改就鍵入新的內(nèi)容,不修改再按空格跳過,如此重復(fù)直到修改完畢,按回車鍵返回DEBUG“-”提示符。如果在修改過程中,將空格鍵換成按“-”鍵,則表示可以修改前一個單元的內(nèi)容。

——————-小抄結(jié)束—————-

5 使用DOS時,匯編用戶可以從DOS操作系統(tǒng)中得到什么?
現(xiàn)在編程,通常很多功能都是通過調(diào)用系統(tǒng)API。很多高級語言都直接把這些API包裝起來,以系統(tǒng)接口或函數(shù)的方式提供給用戶,那么匯編函數(shù)都能得到什么呢?
首先,匯編用戶有很多東西可以調(diào)用。他們主要是:
5.1 BIOS提供的接口。現(xiàn)在硬件與軟件的區(qū)分已越來越不明顯,很多硬件不僅僅是電路,而還要提供一些固化寫入硬件的一部分“程序”,這些程序以ROM的方式出現(xiàn),匯編用戶最大的好處就是可以直接使用這些“程序”,這些使用不僅功能強(qiáng)大,而且效率非常高。
5.2 DOS功能調(diào)用,作為操作系統(tǒng)也象BIOS一樣向用戶提供了相應(yīng)的“程序”。這些程序在很大程序上擴(kuò)充了BIOS。與BIOS不同的是,這部分程序放在內(nèi)存中,它可以被修改。而BIOS中不能再修改。
==========================================================
以上兩種接口都通過一種相同的格式調(diào)用,這些程序統(tǒng)稱為“中斷”,現(xiàn)在先不要理解中斷的本意,你現(xiàn)在可以認(rèn)為是系統(tǒng)提供給你的函數(shù)。
============================================================
5.3 系統(tǒng)共享數(shù)據(jù)區(qū)。編過程序的人都知道全局變量的好處,全局變量方便之外在于任何函數(shù)、過程都可以調(diào)用、讀取、修改。全局變量不足之處是危險性,有一個過程改了這個變量值,其它的也得跟著改變了。DOS操作系統(tǒng)同樣也提供了這樣的共享數(shù)據(jù)區(qū),該區(qū)是整個系統(tǒng)的共享區(qū),任何程序都可以查找、修改。當(dāng)然,修改某處必然會對其它程序造成影響。

6 再談中斷

前面5.2已提到中斷了,現(xiàn)在問題是不同硬件不一樣,即使相同硬件的ROM,不同版本,各個BIOS中斷程序所處的位置也不一樣,DOS中斷也一樣,不同版本、不同配置,在內(nèi)存位置也不一樣。那么你使用某一個中斷,系統(tǒng)怎么知道你使用的那個中斷程序在哪呢?
為了解決這一問題,DOS會在啟動的時候,把所有這些(BIOS和DOS)中斷的首地址保存到一個地址。這個地址很容易記,這段地址是內(nèi)存的絕對零地址(0000:0000)。前面已講過,每個地址在匯編程序員角度來看是二維的,也就是分為段地址和偏移地址。每個地址各占兩個字節(jié),所以要表示這個二維地址需要4個字節(jié)。所以每個中斷首地址由4個字節(jié)表示。一共256個中斷,占用了1024個字節(jié)的位置。
另外需要注意的是,這4個表示地址的字節(jié),數(shù)據(jù)是由低向高的。比如12 34 56 78所表示的地址是:7856:3412。
一般用INT M表示中斷M,如果M是十六進(jìn)制,則在后面加上一個H。比如19號中斷,十六進(jìn)制應(yīng)該是13H。所以該中斷就是INT 13H。

7 再談系統(tǒng)共享數(shù)據(jù)區(qū)

該共享數(shù)據(jù)區(qū)在絕對地址:0040:0000開始。

8 驗證我上面說的內(nèi)容

8.1 找中斷
運(yùn)行DEBUG后。輸入D 0000:0000。顯示絕對零地址的內(nèi)容。
C:\>debug
-d 0:0
0000:0000 68 10 A7 00 8B 01 70 00-16 00 9B 03 8B 01 70 00 h…..p…….p.
0000:0010 8B 01 70 00 B9 06 0E 02-40 07 0E 02 FF 03 0E 02 ..p…..@…….
0000:0020 46 07 0E 02 0A 04 0E 02-3A 00 9B 03 54 00 9B 03 F…….:…T…
0000:0030 6E 00 9B 03 88 00 9B 03-A2 00 9B 03 FF 03 0E 02 n……………
0000:0040 A9 08 0E 02 99 09 0E 02-9F 09 0E 02 5D 04 0E 02 …………]…
0000:0050 A5 09 0E 02 0D 02 DC 02-B8 09 0E 02 8B 05 0E 02 …………….
0000:0060 02 0C 0E 02 08 0C 0E 02-13 0C 0E 02 AD 06 0E 02 …………….
0000:0070 AD 06 0E 02 A4 F0 00 F0-37 05 0E 02 71 84 00 C0 ……..7…q…
-u 0070:018B
0070:018B 1E PUSH DS
0070:018C 50 PUSH AX
0070:018D B84000 MOV AX,0040
0070:0190 8ED8 MOV DS,AX
0070:0192 F70614030024 TEST WORD PTR [0314],2400
0070:0198 754F JNZ 01E9
0070:019A 55 PUSH BP
0070:019B 8BEC MOV BP,SP
0070:019D 8B460A MOV AX,[BP+0A]
0070:01A0 5D POP BP
0070:01A1 A90001 TEST AX,0100
0070:01A4 7543 JNZ 01E9
0070:01A6 A90002 TEST AX,0200
0070:01A9 7422 JZ 01CD
首先,D命令把中斷首地址顯示出來。每4個表示一個地址。其中INT 0的中斷首地址為:00A7:1068,INT 1的中斷地址為:0070:018B…….0070:018B是中斷3的首地址。后面那個U命令就表示顯示該地址的“中斷程序”的內(nèi)存。
你們可以試著找找INT 13H的位置在哪。
8.2 驗證系統(tǒng)共享數(shù)據(jù)區(qū)
系統(tǒng)共享數(shù)據(jù)區(qū)內(nèi)容極為豐富,我實(shí)在記不住哪么多了。我曾記在一個本上,可惜那個本早在N年前(3<n<6)就丟了。兄弟們誰找到這個地址的內(nèi)容,一定要貼上來,這里有東西可以讓大家眼界大開。
前幾年,我用的286計算機(jī)是黑白顯示器(555555~~~~~~~~~,別嫌我老、舊、慢呀),可當(dāng)時有個游戲非要彩顯,不是彩顯不讓運(yùn)行。我就是改了這個區(qū)的某一個位,讓哪游戲“以為”我用的是彩顯,于是游戲能用了。雖然不好看,但總能用。
在DOS下,你每按一個鍵,系統(tǒng)都會記下來,下面我們一起找找這個鍵盤緩沖區(qū)的地址。知道這個地址,你就可以作一個“虛擬”鍵盤,通過發(fā)命令來模擬某個人在按鍵。這個地址位于:0040:001E。 其中每個鍵有兩個字節(jié),一個字節(jié)是ASCII碼,一個是掃描碼。共16個。
C:\>debug
-d 40:0
0040:0000 F8 03 F8 02 E8 03 E8 02-BC 03 78 03 78 02 80 9F ……….x.x…
0040:0010 22 C8 00 80 02 28 00 00-00 00 2A 00 2A 00 20 39 "….(….*.*. 9
0040:0020 34 05 30 0B 3A 27 30 0B-0D 1C 64 20 20 39 34 05 4.0.:'0…d 94.
0040:0030 30 0B 3A 27 30 0B 0D 1C-71 10 0D 1C 64 20 00 00 0.:'0…q…d ..
0040:0040 A2 00 C3 00 A2 AF 09 E1-C8 03 50 00 00 10 00 00 ……….P…..
0040:0050 00 18 00 00 00 00 00 00-00 00 00 00 00 00 00 00 …………….
0040:0060 0F 0C 00 D4 03 29 30 7F-03 00 C0 00 A1 B7 11 00 …..)0………
0040:0070 00 00 00 00 00 00 00 00-14 14 14 00 01 01 01 01 …………….
-d 0040:0000
0040:0000 F8 03 F8 02 E8 03 E8 02-BC 03 78 03 78 02 80 9F ……….x.x…
0040:0010 22 C8 00 80 02 28 00 00-00 00 2A 00 2A 00 3A 27 "….(….*.*.:'
0040:0020 30 0B 30 0B 30 0B 30 0B-0D 1C 64 20 20 39 30 0B 0.0.0.0…d 90.
0040:0030 30 0B 30 0B 30 0B 08 0E-08 0E 34 05 30 0B 00 00 0.0.0…..4.0…
0040:0040 1F 00 C3 00 A2 AF 09 E1-C8 03 50 00 00 10 00 00 ……….P…..
0040:0050 00 18 00 00 00 00 00 00-00 00 00 00 00 00 00 00 …………….
0040:0060 0F 0C 00 D4 03 29 30 7F-03 00 C0 00 24 B8 11 00 …..)0…..$…
0040:0070 00 00 00 00 00 00 00 00-14 14 14 00 01 01 01 01 …………….
-
既然是鍵盤緩沖區(qū),每個輸入的鍵都會顯示在該區(qū)中,第一次我只輸入了“d 40:0”,所以你可以在此后顯示數(shù)據(jù)右邊字符中找到這些字符,注意是間隔開的。
第二次我輸入“d 0040:0000”,則右邊顯示的是“d 0040:0000”的內(nèi)容。你可以找找。

第二講 內(nèi)存映象

之所以把這個內(nèi)存單獨(dú)放一章,是為了說明它的重要性,后面的幾乎很多程序都需要你對這一章的理解。這里的內(nèi)存映象就是指當(dāng)你把一個可執(zhí)行文件(EXE或COM文件)放到內(nèi)存后,整個內(nèi)存“看”起來是什么樣子的。
前面講過,這里匯編程序只能訪問1M的內(nèi)存空間,所以下面就以1M內(nèi)存為例。并且以DOS操作系統(tǒng)作為講解對象,所以所編出來的程序也僅是DOS程序。事實(shí)上,通過winasm可以訪問遠(yuǎn)遠(yuǎn)超過1M的空間,并且可以編出FOR windows的程序。但那是另外的話題。我們暫且不說那些。

2.1 內(nèi)存映象
首先,這1M內(nèi)存如果我們不再以二維的方式看,而是一維的,線性地看(二維和一維的轉(zhuǎn)化方式參見前面章節(jié))。但描述還是以二維的方式描述,從最底端到最高端依次是:
1 中斷向量區(qū):該區(qū)由0000:0000~0000:03FF。這里存著系統(tǒng)的所有中斷的中斷向量表,對于中斷向量表,你現(xiàn)在先理解為一些程序的首地址。由這個地址你就能找到該程序。
2 系統(tǒng)數(shù)據(jù)區(qū):該區(qū)由0040:0000~0040:XXXX(不好意思,忘了),這里存著整個系統(tǒng)中,DOS操作系統(tǒng)要用的數(shù)據(jù),由于這個區(qū)的數(shù)據(jù)對用戶是開放的,所以用戶當(dāng)然也可以從這里讀出來用。
3 DOS操作系統(tǒng)區(qū):操作系統(tǒng)常駐內(nèi)存,你向計算機(jī)發(fā)的每個命令其實(shí)都是操作系統(tǒng)執(zhí)行的。這個區(qū)的大小主要是由操作系統(tǒng)的版本和用戶的配置大小決定,如果是驅(qū)動程序配置,就放到根目錄下的config.sys里,如果是程序,就放到autoexec.bat里。這里設(shè)置在現(xiàn)在的windows 95/98/nt/me/2000/xp/2003中仍然有,所以我就不多說了。
4 用戶程序,這個當(dāng)然就是你執(zhí)行的程序了,這種程序分兩種,一種是擴(kuò)展名為com文件,一種是exe文件,從程序內(nèi)睝@矗罷叱絳虻乃母齠沃睪希ê竺嬉艙饉母齠危宰畬蟪ざ戎壞扔諞桓齠危們懊娑蔚刂返睦斫餼褪莄om文件最大只能是64K,所以com文件只適合小的程序。而exe,四個段可任何分配,并可擴(kuò)充段,而且每個段的段地址可以任何改動,因此exe的訪問內(nèi)存能力大多了。這種格式訪問能力只受地址結(jié)構(gòu)的限制了。
用戶程序所占的內(nèi)存大小完全由程序本身決定,但最大,只能到640K。這一點(diǎn),怪不得別人,只能怪當(dāng)前計算機(jī)軟硬件設(shè)置高手高手高高手們(包括比爾蓋茨)們的失誤了,60年代的超級計算機(jī)只有36K的內(nèi)存,所以他們就在80年代得到一個結(jié)論:640K的內(nèi)存足夠了。
如果用戶程序大于由操作系統(tǒng)所占內(nèi)存的頂?shù)椎?40K之間的內(nèi)存量,就會顯示:內(nèi)存不夠,因而程序不能執(zhí)行。這種現(xiàn)象對于一開始就用windows的人來說,幾乎沒見過,但對于一開始用DOS并打漢字的人來說,再正常不過。如果小于這段內(nèi)存,多余部分就空著。
5 從640K到1M-64K,這段內(nèi)存就很難說清了。這段內(nèi)存中有一部分被硬件占有,有一部分是顯示緩沖區(qū)點(diǎn)有,還有一部分是系統(tǒng)ROM占有。
6 從1M-64K到1M之間的這段64K的內(nèi)存叫作HMA。這段內(nèi)存是小孩沒娘,說來話長,我們先不說他。
2.2 驗證上面的理論

2.2.1 中斷向量表
中斷向量表就是所有中斷向量首地址表,這里保存著每個中斷程序的首地址,幾乎所有的匯編書都把中斷后面后面的章節(jié)中,并且對中斷的解釋也僅從字面意思解釋,所以導(dǎo)致大學(xué)對中斷的不重要和誤解。沒耐心的沒到這個章節(jié)就不學(xué)匯編了,有耐心的到這里才豁然開朗。我現(xiàn)在不講中斷的原意。我直接告訴你,你把中斷當(dāng)成API也許更合適。也就是說,別人把很多已作好的功能放到了內(nèi)存中。并且把調(diào)用這一功能的號告訴了你,你只要調(diào)用這些功能號,系統(tǒng)就自動從這個中斷向量表中找到對應(yīng)的中斷,然后執(zhí)行你的功能。
首先讓你感受一下中斷的魅力一下吧。比如中斷21H的2A功能調(diào)用是讀取系統(tǒng)的日期,這個調(diào)用的規(guī)則是,調(diào)用前AH寄存器置為2A。調(diào)用后年在CX中,月在DH中,DL在日中,星期在AL中。
-a
139D:0100 mov ah,2a
139D:0102 int 21
139D:0104 int 3
139D:0105
-g=100

AX=2A05 BX=0000 CX=07D4 DX=0C18 SP=FFEE BP=0000 SI=0000 DI=0000
DS=139D ES=139D SS=139D CS=139D IP=0104 NV UP EI PL NZ NA PO NC
139D:0104 CC INT 3
-
可能上面的程序你目前還看不懂。不過沒關(guān)系,“mov ah,2a”表示調(diào)用功能號是2a號。“int 21”表示調(diào)用十六進(jìn)制21號中斷,“int 3”表示3號中斷,表示程序運(yùn)行到這一句時停一下。“g=100”表示從“139D:0100 ”開始執(zhí)行。
AX=2A05 BX=0000 CX=07D4 DX=0C18 SP=FFEE BP=0000 SI=0000 DI=0000
DS=139D ES=139D SS=139D CS=139D IP=0104 NV UP EI PL NZ NA PO NC
表示執(zhí)行的結(jié)果。其中CX是年,這個年是由CX中存。07D4十進(jìn)制就是2004年。DH+DL=DX,所以DH=0C,DL=18。二者轉(zhuǎn)化為十進(jìn)制就是DH=12,DL=24,也就是今天了。AX=AH+AL=2A05,所以AL=05。那就是今天是星期五。
上面可能你們現(xiàn)在還看不懂,不過通過解說你應(yīng)該可以知道,僅僅兩行命令,就讀到了現(xiàn)在的值。現(xiàn)在需要作的就是把這些值提取出來用作他用了。

從中斷的作來與中斷向量表又有什么關(guān)系呢?原來你在匯編里運(yùn)行int 21時,系統(tǒng)就在上面的中斷向量表中找到int 21的中斷地址,該中斷的地址應(yīng)該位于:0000:0084~0000:0087,具體算法前面已說明了。
-d 0000:0084 0087
0000:0080 7C 10 A7 00 |…
-
找到內(nèi)容是:00A7:107C。然后系統(tǒng)就轉(zhuǎn)到這個地址執(zhí)行int 21。

2.2.2 系統(tǒng)數(shù)據(jù)區(qū)前面都已說明過。不再多說。系統(tǒng)區(qū),很多DOS中斷程序?qū)崿F(xiàn)部分就在這個區(qū)。程序運(yùn)行區(qū)依不同的程序而不用。

2.2.3 640K~1M之間,這期間有些地方是ROM,有些地方是硬件的BIOS區(qū)。我僅以兩個例子說明這一區(qū)。
ROM區(qū):ROM區(qū)就是只讀內(nèi)存,也就是說這個區(qū)的數(shù)據(jù)只能讀不能寫。比如F000:0000開始的內(nèi)存是ROM。我們來寫一下,然后再看看效果。
-d f000:0000 0005 '顯示由F000:0000到F000:0005的六個字節(jié)值。
F000:0000 04 E8 A2 FF F9 C3 ……
-e f000:0000 '修改命令
F000:0000 04.00 E8.00 A2.00 FF.00 F9.00 C3.00'注意,.后面的是我改的,把這幾個值都改成0了。
-d f000:0000 0005 '再次顯示這個區(qū)的數(shù)據(jù)。
F000:0000 04 E8 A2 FF F9 C3 ……
-
通過上面測試,發(fā)現(xiàn)該區(qū)數(shù)據(jù)仍然未改變。但你要是試別的RAM區(qū)的,肯定會變。如果想試你自己試試吧。

顯示緩沖區(qū):在文本方式下,B800:0000開始的地址保存著屏幕上每個字符位置的值。在文本方式下,屏幕被分為80 X 25。每個位置有兩個值,一個值是ASCII字符,一個值是該ASCII的屬性值(主要是顏色)。所以一個屏幕共有80X25X2=400個字符。
我們來改:
-d b800:0000 0010 '顯示屏幕緩沖區(qū)的內(nèi)容,注意此時本行最左邊的“-”是屏幕左上角。
B800:0000 2D 07 64 07 20 07 62 07-38 07 30 07 30 07 3A 07 -.d. .b.8.0.0.:.
B800:0010 30 0
-
看上面的命令,屏幕最上邊一行是“-d b800:0000 0010”,所以他的內(nèi)容就是“2D 07 64 07 20 07 62 07-38 07 30 07 30 07 3A 07”其中,2D是“-”的ASCII值,07是“-”的屬性值。64是“d”的ASCII值,07是“d”的屬性值。。。。。
現(xiàn)在修改這些值。我把左上角的字改成黃顏色的“-”,那當(dāng)然是改b800:0001的屬性值了。
-e b800:0001 0e
是不是左上角的顏色變成黃色了嗎?
好了,把第二個字符變成綠色的“-”吧?
-e b800:0002 2d 0b
變了嗎?

第三章 匯編指令

3.1 什么是機(jī)器語言
前面提到“最早的計算機(jī)采用機(jī)器語言,這種語言直接用二進(jìn)制數(shù)表示,通過直接輸入二進(jìn)制數(shù),插拔電路板等實(shí)現(xiàn),這種“編程”很容易出錯,每個命令都是通過查命令表實(shí)現(xiàn)”。
比如要執(zhí)行21號中斷,需要查表,得到21號中斷的指令就是CD 21。這樣不管你通過什么方式,在內(nèi)存指令位置,寫入兩個字節(jié),一個是CD(這可不是音樂光盤,而是二進(jìn)制數(shù),轉(zhuǎn)成十進(jìn)制就是205),另一個是21(同樣是十六進(jìn)制,十進(jìn)制是33)。
上面就是機(jī)器語言。

3.2 什么是匯編語言
前面也提到“既然是通過“查表”實(shí)現(xiàn)的,那當(dāng)然也可以讓計算機(jī)來代替人查表實(shí)現(xiàn)了。于是就產(chǎn)生了匯編語言”,匯編語言產(chǎn)生的重要目的就是用容易記的符號來代替容易出錯的二進(jìn)制數(shù)(或十六進(jìn)制數(shù))。
比如前面的21號中斷,機(jī)器語言是CD 21。而匯編語言就規(guī)定中斷用int表示(interrupt的前三個字母),21號中斷就成了int 21h。其中21后面的h表示是表示這個21是十六進(jìn)制。由于大小寫不敏感,所以int 21h寫成下列方式都等價:
int 33
Int 21h
INT 21H

3.3 匯編指令集

一、數(shù)據(jù)傳輸指令

───────────────────────────────────────
它們在存貯器和寄存器、寄存器和輸入輸出端口之間傳送數(shù)據(jù).
1. 通用數(shù)據(jù)傳送指令.
MOV 傳送字或字節(jié).
MOVSX 先符號擴(kuò)展,再傳送.
MOVZX 先零擴(kuò)展,再傳送.
PUSH 把字壓入堆棧.
POP 把字彈出堆棧.
PUSHA 把AX,CX,DX,BX,SP,BP,SI,DI依次壓入堆棧.
POPA 把DI,SI,BP,SP,BX,DX,CX,AX依次彈出堆棧.
PUSHAD 把EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI依次壓入堆棧.
POPAD 把EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX依次彈出堆棧.
BSWAP 交換32位寄存器里字節(jié)的順序
XCHG 交換字或字節(jié).( 至少有一個操作數(shù)為寄存器,段寄存器不可作為操作數(shù))
CMPXCHG 比較并交換操作數(shù).( 第二個操作數(shù)必須為累加器AL/AX/EAX )
XADD 先交換再累加.( 結(jié)果在第一個操作數(shù)里 )
XLAT 字節(jié)查表轉(zhuǎn)換.
── BX 指向一張 256 字節(jié)的表的起點(diǎn), AL 為表的索引值 (0-255,即
0-FFH); 返回 AL 為查表結(jié)果. ( [BX+AL]->AL )
2. 輸入輸出端口傳送指令.
IN I/O端口輸入. ( 語法: IN 累加器, {端口號│DX} )
OUT I/O端口輸出. ( 語法: OUT {端口號│DX},累加器 )
輸入輸出端口由立即方式指定時, 其范圍是 0-255; 由寄存器 DX 指定時,
其范圍是 0-65535.
3. 目的地址傳送指令.
LEA 裝入有效地址.
例: LEA DX,string ;把偏移地址存到DX.
LDS 傳送目標(biāo)指針,把指針內(nèi)容裝入DS.
例: LDS SI,string ;把段地址:偏移地址存到DS:SI.
LES 傳送目標(biāo)指針,把指針內(nèi)容裝入ES.
例: LES DI,string ;把段地址:偏移地址存到ES:DI.
LFS 傳送目標(biāo)指針,把指針內(nèi)容裝入FS.
例: LFS DI,string ;把段地址:偏移地址存到FS:DI.
LGS 傳送目標(biāo)指針,把指針內(nèi)容裝入GS.
例: LGS DI,string ;把段地址:偏移地址存到GS:DI.
LSS 傳送目標(biāo)指針,把指針內(nèi)容裝入SS.
例: LSS DI,string ;把段地址:偏移地址存到SS:DI.
4. 標(biāo)志傳送指令.
LAHF 標(biāo)志寄存器傳送,把標(biāo)志裝入AH.
SAHF 標(biāo)志寄存器傳送,把AH內(nèi)容裝入標(biāo)志寄存器.
PUSHF 標(biāo)志入棧.
POPF 標(biāo)志出棧.
PUSHD 32位標(biāo)志入棧.
POPD 32位標(biāo)志出棧.

二、算術(shù)運(yùn)算指令

───────────────────────────────────────
ADD 加法.
ADC 帶進(jìn)位加法.
INC 加 1.
AAA 加法的ASCII碼調(diào)整.
DAA 加法的十進(jìn)制調(diào)整.
SUB 減法.
SBB 帶借位減法.
DEC 減 1.
NEC 求反(以 0 減之).
CMP 比較.(兩操作數(shù)作減法,僅修改標(biāo)志位,不回送結(jié)果).
AAS 減法的ASCII碼調(diào)整.
DAS 減法的十進(jìn)制調(diào)整.
MUL 無符號乘法.
IMUL 整數(shù)乘法.
以上兩條,結(jié)果回送AH和AL(字節(jié)運(yùn)算),或DX和AX(字運(yùn)算),
AAM 乘法的ASCII碼調(diào)整.
DIV 無符號除法.
IDIV 整數(shù)除法.
以上兩條,結(jié)果回送:
商回送AL,余數(shù)回送AH, (字節(jié)運(yùn)算);
或 商回送AX,余數(shù)回送DX, (字運(yùn)算).
AAD 除法的ASCII碼調(diào)整.
CBW 字節(jié)轉(zhuǎn)換為字. (把AL中字節(jié)的符號擴(kuò)展到AH中去)
CWD 字轉(zhuǎn)換為雙字. (把AX中的字的符號擴(kuò)展到DX中去)
CWDE 字轉(zhuǎn)換為雙字. (把AX中的字符號擴(kuò)展到EAX中去)
CDQ 雙字?jǐn)U展. (把EAX中的字的符號擴(kuò)展到EDX中去)

三、邏輯運(yùn)算指令

───────────────────────────────────────
AND 與運(yùn)算.
or 或運(yùn)算.
XOR 異或運(yùn)算.
NOT 取反.
TEST 測試.(兩操作數(shù)作與運(yùn)算,僅修改標(biāo)志位,不回送結(jié)果).
SHL 邏輯左移.
SAL 算術(shù)左移.(=SHL)
SHR 邏輯右移.
SAR 算術(shù)右移.(=SHR)
ROL 循環(huán)左移.
ROR 循環(huán)右移.
RCL 通過進(jìn)位的循環(huán)左移.
RCR 通過進(jìn)位的循環(huán)右移.
以上八種移位指令,其移位次數(shù)可達(dá)255次.
移位一次時, 可直接用操作碼. 如 SHL AX,1.
移位>1次時, 則由寄存器CL給出移位次數(shù).
如 MOV CL,04
SHL AX,CL

四、串指令

───────────────────────────────────────
DS:SI 源串段寄存器 :源串變址.
ES:DI 目標(biāo)串段寄存器:目標(biāo)串變址.
CX 重復(fù)次數(shù)計數(shù)器.
AL/AX 掃描值.
D標(biāo)志 0表示重復(fù)操作中SI和DI應(yīng)自動增量; 1表示應(yīng)自動減量.
Z標(biāo)志 用來控制掃描或比較操作的結(jié)束.
MOVS 串傳送.
( MOVSB 傳送字符. MOVSW 傳送字. MOVSD 傳送雙字. )
CMPS 串比較.
( CMPSB 比較字符. CMPSW 比較字. )
SCAS 串掃描.
把AL或AX的內(nèi)容與目標(biāo)串作比較,比較結(jié)果反映在標(biāo)志位.
LODS 裝入串.
把源串中的元素(字或字節(jié))逐一裝入AL或AX中.
( LODSB 傳送字符. LODSW 傳送字. LODSD 傳送雙字. )
STOS 保存串.
是LODS的逆過程.
REP 當(dāng)CX/ECX<>0時重復(fù).
REPE/REPZ 當(dāng)ZF=1或比較結(jié)果相等,且CX/ECX<>0時重復(fù).
REPNE/REPNZ 當(dāng)ZF=0或比較結(jié)果不相等,且CX/ECX<>0時重復(fù).
REPC 當(dāng)CF=1且CX/ECX<>0時重復(fù).
REPNC 當(dāng)CF=0且CX/ECX<>0時重復(fù).

五、程序轉(zhuǎn)移指令

───────────────────────────────────────
1>無條件轉(zhuǎn)移指令 (長轉(zhuǎn)移)
JMP 無條件轉(zhuǎn)移指令
CALL 過程調(diào)用
RET/RETF過程返回.
2>條件轉(zhuǎn)移指令 (短轉(zhuǎn)移,-128到+127的距離內(nèi))
( 當(dāng)且僅當(dāng)(SF XOR OF)=1時,OP1<op2 )
JA/JNBE 不小于或不等于時轉(zhuǎn)移.
JAE/JNB 大于或等于轉(zhuǎn)移.
JB/JNAE 小于轉(zhuǎn)移.
JBE/JNA 小于或等于轉(zhuǎn)移.
以上四條,測試無符號整數(shù)運(yùn)算的結(jié)果(標(biāo)志C和Z).
JG/JNLE 大于轉(zhuǎn)移.
JGE/JNL 大于或等于轉(zhuǎn)移.
JL/JNGE 小于轉(zhuǎn)移.
JLE/JNG 小于或等于轉(zhuǎn)移.
以上四條,測試帶符號整數(shù)運(yùn)算的結(jié)果(標(biāo)志S,O和Z).
JE/JZ 等于轉(zhuǎn)移.
JNE/JNZ 不等于時轉(zhuǎn)移.
JC 有進(jìn)位時轉(zhuǎn)移.
JNC 無進(jìn)位時轉(zhuǎn)移.
JNO 不溢出時轉(zhuǎn)移.
JNP/JPO 奇偶性為奇數(shù)時轉(zhuǎn)移.
JNS 符號位為 "0" 時轉(zhuǎn)移.
JO 溢出轉(zhuǎn)移.
JP/JPE 奇偶性為偶數(shù)時轉(zhuǎn)移.
JS 符號位為 "1" 時轉(zhuǎn)移.
3>循環(huán)控制指令(短轉(zhuǎn)移)
LOOP CX不為零時循環(huán).
LOOPE/LOOPZ CX不為零且標(biāo)志Z=1時循環(huán).
LOOPNE/LOOPNZ CX不為零且標(biāo)志Z=0時循環(huán).
JCXZ CX為零時轉(zhuǎn)移.
JECXZ ECX為零時轉(zhuǎn)移.
4>中斷指令
INT 中斷指令
INTO 溢出中斷
IRET 中斷返回
5>處理器控制指令
HLT 處理器暫停, 直到出現(xiàn)中斷或復(fù)位信號才繼續(xù).
WAIT 當(dāng)芯片引線TEST為高電平時使CPU進(jìn)入等待狀態(tài).
ESC 轉(zhuǎn)換到外處理器.
LOCK 封鎖總線.
NOP 空操作.
STC 置進(jìn)位標(biāo)志位.
CLC 清進(jìn)位標(biāo)志位.
CMC 進(jìn)位標(biāo)志取反.
STD 置方向標(biāo)志位.
CLD 清方向標(biāo)志位.
STI 置中斷允許位.
CLI 清中斷允許位.

六、偽指令

───────────────────────────────────────
DW 定義字(2字節(jié)).
PROC 定義過程.
ENDP 過程結(jié)束.
SEGMENT 定義段.
ASSUME 建立段寄存器尋址.
ENDS 段結(jié)束.
END 程序結(jié)束.
3.4 再談寄存器和內(nèi)存的區(qū)別
第零講說到“寄存器在CPU中。內(nèi)存在內(nèi)存條中。前者的速度比后者快100倍左右。后面的程序要求每條指定要么沒有內(nèi)存數(shù)據(jù),要么在有一個寄存器的參與下有一個內(nèi)存數(shù)據(jù)。(也就是說,不存在只訪問內(nèi)存的指令)。”
寄存器是在CPU中的存儲器,而內(nèi)存是在內(nèi)存條中的存儲器。CPU訪問寄存器,只需要通過微指令直接就可以訪問,而訪問內(nèi)存則要先經(jīng)過總線,再由總線到達(dá)內(nèi)存控制器,讀到某單元的內(nèi)存數(shù)據(jù)后放上總線,再傳到CPU中,CPU才能使用。
8086系列計算機(jī)的寄存器,共有14個,每個都是十六位的。
AX,BX,CX,DX,SP,BP,SI,DI,CS,DS,SS,ES,IP,F(xiàn)LAGS。
其中前四位,每個可以單位再分成兩個,AX=AH+AL,BX=BH+BL,CX=CH+CL,DX=DH+DL。這些分開的每個都是8位的。
這個分開不要理解成平時語言中的分開,你可以理解為AX是由AH和AL組合成的,你給AL付值,就意味著同時給AX的低半部付值。你給AX付值,就意味著同時改變AH和AL。這樣作的好處是你可以更靈活地控制這個寄存器。

3.5 指令說明
看了3.3的指令集和3.4的寄存器,是不是已經(jīng)了,或者了?不要急,上面的東西雖然多,我也沒讓你一下學(xué)會,(其實(shí)有些永遠(yuǎn)也不會似乎也不是什么大不了的事)。為了應(yīng)付看的懂我后面所說的,我把其中的指令挑幾個重點(diǎn)的,你必須要記住,其它的慢慢學(xué)吧。

1數(shù)據(jù)傳輸指令。
mov A,B
注意不是move,這個指令是把B中的數(shù)據(jù)復(fù)制給A,(B中仍保存原狀)。這里的A和B可以是寄存器,可以是內(nèi)存。但可以同時是寄存器,不能同時是內(nèi)存。比如
mov ax,100 ;這是對的,注意100在這里叫立即數(shù),但這個數(shù)在編譯系統(tǒng)編譯成exe的時候保存在內(nèi)存中。如果學(xué)過別的高級語言,你就可以理解為這就是賦值語句 Let ax=100/ax:=100;/ax=100。
2 偽指令
偽指令就是不是真的指令,但他同時又是指令。之所以說這樣矛盾的話,是因為偽指令不是機(jī)器語言的一部分,而是匯編語言的一部分,是你告訴匯編的編譯系統(tǒng)如何去作。
string DB '這是我的第一個匯編語言程序$'
上面一行指令中,DB就是偽指令,他的作用就是告訴編譯程序,把后面一些數(shù)據(jù)或字符串放到內(nèi)存中。當(dāng)然對于exe來說,已在內(nèi)存中了,就不用“告訴”了。(這就是為什么叫偽指令)。string是你給這段內(nèi)存起的名字,如果你不需要這段內(nèi)存,不起名字也可以,但如果后面要用,當(dāng)然要加上這個名字。'這是我的第一個匯編語言程序$'這個就是要處理的數(shù)據(jù),當(dāng)然你也可以換成別的內(nèi)容,但需要注意的是,要以'$'結(jié)尾,這是匯編的約寫,即:只是到了$,就認(rèn)為字符串結(jié)束,否則就一直向下找,直到找到一個$為止。所以這就要求你的字符串中不能有'$',如果必須有,再換別的處理方式,后面再說。
3 地址傳送指令
Lea A,string
前面已經(jīng)定義了string,后面要把地址找到,就要用到lea指令。lea是把字符串的地址給A這個寄存器中,A當(dāng)然可以上前面提到的任意寄存器。注意地址和內(nèi)容的區(qū)別。如果是內(nèi)容就是把string的字符串給A了。(當(dāng)然這也不成立,一個字符串有很多字節(jié),而一個寄存器只有兩個字節(jié))。
那么從上面也看到了,string代表一個地址,lea把這個地址給了A,那這個地址到底在哪里呢?事實(shí)上這不重要,就象你要把某書店買書,這個書店在哪并不是最重要的,有沒有你要的書才是最重要的。所以你前面標(biāo)出string,后面引用就行了,至于這個地址到底在哪是編譯程序的事,不是你的事。

4 運(yùn)算指令
ADD A,N
這個很容易理解吧,寄存器A加上N,把和仍存在A中。類似于高級語言中的let a=a+n/a:=a+n/a+=n。

5 串操作指令
記住串操作指令表面很復(fù)雜,其實(shí)很簡單。
因為他就象一個復(fù)雜的數(shù)學(xué)公式一樣簡單,你所要記住的就是公式的格式,使用時具體套用即可。
從一個地址到另一個地址的復(fù)制需要注意的是:
*把源串段地址給DS。
*把源串編址給SI。
*把目的串段址給ES。
*把目的串偏址給DI。
*把要復(fù)制的個數(shù)給CX,這里可不考慮$了。
*把FLAG中的方向標(biāo)志標(biāo)志你要的方向,一個是順向,另一個是逆向。
*發(fā)送loop movs,scans等命令。

6 轉(zhuǎn)移指令
記住:無條件轉(zhuǎn)移指令 jmp。等于轉(zhuǎn) jz,不等于時轉(zhuǎn)jnz

7 中斷指令
int 中斷號,注意進(jìn)制,默認(rèn)是十進(jìn)制,所以十六進(jìn)制就加h。

好了,上面的指令變成七八個了,這你不能嫌多了吧,如果再嫌多就不要繼續(xù)向下看了。

4.1 匯編程序框架

data SEGMENT '數(shù)據(jù)段,編程者可以把數(shù)據(jù)都放到這個段里
….數(shù)據(jù)部分
'數(shù)據(jù)格式是: 標(biāo)識符 db/dw 數(shù)據(jù)。
data ENDS'數(shù)據(jù)段結(jié)束處。

edata SEGMENT '附加數(shù)據(jù)段,編程者可以把數(shù)據(jù)都放到這個段里
….附加數(shù)據(jù)部分
edata ENDS'附加數(shù)據(jù)段結(jié)束處。

code SEGMENT'代碼段,實(shí)際的程序都是放這個段里。
ASSUME CS:code,DS:data,ES:edata '告訴編譯程序,data段是數(shù)據(jù)段DS,code段是代碼段CS
start:MOV AX,data '前面的start表示一個標(biāo)識位,后面用到該位,如果用不到,就可以不加
MOV DS,AX '這一句與上一行共同組成把data賦值給DS。段寄存器.
MOV AX,edata
MOV ES,AX '與前一句共同組成edata->ES
…….程序部分
MOV AX,4C00h'程序退出,該句內(nèi)存由下一行決定。退出時,要求ah必須是4c。
INT 21h
code ENDS'代碼段結(jié)束。
END start'整個程序結(jié)束,并且程序執(zhí)行時由start那個位置開始執(zhí)行。

上面就是一個程序的框架結(jié)構(gòu)。在這個結(jié)構(gòu)中,有三個段,DS,ES,CS。這三個段分別存數(shù)據(jù),附加數(shù)據(jù),代碼段。

4.2 編寫我們的Hello,world思路。
開始編寫我們的第一個程序。
程序要求:顯示一個“Hello,Mr.286.”怎么樣?
思路:
1 要顯示一個字符串,根據(jù)前面我讓你們記的七八個指令夠嗎?答案是:不僅夠,而且還用不完。
首先定義一下總可以吧。

hellostr db 'Hello,Mr.286.$'
最后的$不要忘了。

2 首先要考慮的問題就是找中斷,找到合適的中斷,該中斷就能幫我們完成這個顯示任務(wù)。我找到(在哪找到的,怎么找到的,別問我,到網(wǎng)上或書上都能找到):
——————————————-
中斷INT 21H功能09H

功能描述: 輸出一個字符串到標(biāo)準(zhǔn)輸出設(shè)備上。如果輸出操作被重定向,那么,將無法判斷磁盤已滿
入口參數(shù): AH=09H
DS:DX=待輸出字符的地址
說明:待顯示的字符串以'$'作為其結(jié)束標(biāo)志
出口參數(shù): 無
——————————————-
由上面看到,我們所需要作的就是把DS指向數(shù)據(jù)段,DX指向字符串的地址,AH等于9H,調(diào)用21h中斷。
mov ds,數(shù)據(jù)段地址
lea dx,hellostr 'hellostr已在前面1中定義了。
mov ah,9h
int 21h。
由于只要在調(diào)用int 21h之前把準(zhǔn)備的東西準(zhǔn)備齊就行了,所以int 21h前面三行的順序并不重要。

3 退出程序,運(yùn)行完總要退出呀。再查中斷手冊
——————————————–
中斷INT 21H功能4CH

功能描述: 終止程序的執(zhí)行,并可返回一個代碼
入口參數(shù): AH=4CH
AL=返回的代碼
出口參數(shù): 無

——————————————–
mov ah,4Ch
mov al,0
int 21h

mov ax,4c00h
int 21h
這里需要說明的是返回代碼有什么用,返回給誰?返回給操作系統(tǒng),因為是操作系統(tǒng)DOS調(diào)用的這個程序,這個返回值可以通過批處理中的errorlevel得到,這里不多說明,實(shí)際上操作系統(tǒng)很少處理這一值,因此al你隨便寫什么值影響都不大。

4.3 程序?qū)崿F(xiàn)


data SEGMENT
msg DB 'Hello, Mr.286.$'
data ENDS

code SEGMENT
ASSUME CS:code,DS:data
start:MOV AX,data
MOV DS,AX
lea dx,msg
mov ah,9h
int 21h
MOV AX,4C00h
INT 21h
code ENDS
END start

4.4 編譯運(yùn)行。
把上面程序保存成hello286.asm后,就可以編譯運(yùn)行了。進(jìn)入DOS,進(jìn)入?yún)R編目錄,如果還沒下載,到前面找下載地址。

=================================================
E:\Download\Masm>masm hello286.asm
Microsoft (R) Macro Assembler Version 5.00
Copyright (C) Microsoft Corp 1981-1985, 1987. All rights reserved.

Object filename [hello286.OBJ]:
Source listing [NUL.LST]:
Cross-reference [NUL.CRF]:

50408 + 415320 Bytes symbol space free

0 Warning Errors
0 Severe Errors
說明:上面連續(xù)三個回車,表示我要的都是默認(rèn)值。下面是零個警告,零個嚴(yán)重錯誤,(當(dāng)然了,我的程序還敢錯嗎?)

E:\Download\Masm>link hello286

Microsoft (R) Overlay Linker Version 3.60
Copyright (C) Microsoft Corp 1983-1987. All rights reserved.

Run File [HELLO286.EXE]:
List File [NUL.MAP]:
Libraries [.LIB]:
LINK : warning L4021: no stack segment

說明:三個回車仍要默認(rèn),后面有個警告,沒有棧段,這個沒關(guān)系,沒有的話系統(tǒng)會自動給一個()。

E:\Download\Masm>hello286
Hello, Mr.286.
說明:運(yùn)行成功。
E:\Download\Masm>
===================================================
4.4 深度思考
4.4.1 是不是數(shù)據(jù)必須放數(shù)據(jù)段,代碼必段放代碼段呢?
答,代碼必段放代碼段,否則你怎么執(zhí)行呀?但數(shù)據(jù)也可以放到代碼段,只是程序要作修改。

code SEGMENT
ASSUME CS:code,DS:data
msg DB 'Hello, Mr.286.$'
start:MOV AX,data
MOV DS,AX
lea dx,msg
mov ah,9h
int 21h
MOV AX,4C00h
INT 21h
code ENDS
END start

編譯后仍然可以。
4.4.2 我編的程序在內(nèi)存中是什么樣子的呢?
————————————————————————
E:\Download\Masm>debug hello286.exe
-u
1420:0000 B81F14 MOV AX,141F
1420:0003 8ED8 MOV DS,AX
1420:0005 8D160000 LEA DX,[0000]
1420:0009 B409 MOV AH,09
1420:000B CD21 INT 21
1420:000D B8004C MOV AX,4C00
1420:0010 CD21 INT 21
1420:0012 FF362421 PUSH [2124]
1420:0016 E87763 CALL 6390
1420:0019 83C406 ADD SP,+06
1420:001C FF362421 PUSH [2124]
-d 141f:0000 L20
141F:0000 48 65 6C 6C 6F 2C 20 4D-72 2E 32 38 36 2E 24 00 Hello, Mr.286.$.
141F:0010 B8 1F 14 8E D8 8D 16 00-00 B4 09 CD 21 B8 00 4C …………!..L
-q

E:\Download\Masm>
——————————————————————————
上面是什么呀?,還記得前面說的嗎?
1420:0000 B81F14 MOV AX,141F
| | | | |
段址:偏址 機(jī)器語言 mov指令 把段地址的地址(141f)賦值給AX寄存器。

1420:0012后面的是垃圾數(shù)據(jù),不用管它,把上面程序與源程序作一個比較,看有什么不用,差別在于把標(biāo)號語言轉(zhuǎn)成實(shí)際地址了。
程序前兩行一執(zhí)行,數(shù)據(jù)段地址就變成了141f,而那個字符串偏移地址在0000,由(LEA DX,[0000]看出),所以我用-d 141f:0000 L20(后面L20表示只顯示20個字節(jié)),就能把段地址顯示出來了。
所以剛才的程序在內(nèi)存中就變成了:
141f:0000 Hello, Mr.286.$ —–>這是段地址里的內(nèi)存
1420:0000 B81F14 MOV AX,141F ——>這是代碼段里的內(nèi)存。data變成了實(shí)際地址
1420:0003 8ED8 MOV DS,AX
1420:0005 8D160000 LEA DX,[0000] ——>偏址變成了0000,因為實(shí)際上msg也就是從頭開始的。當(dāng)然是0了。
1420:0009 B409 MOV AH,09 ——->注意Debug里,默認(rèn)的是十六進(jìn)制
1420:000B CD21 INT 21
1420:000D B8004C MOV AX,4C00
1420:0010 CD21 INT 21
剛剛學(xué)習(xí)了8086/8088匯編語言,發(fā)現(xiàn)尋址方式非常重要,于是做了一個小總結(jié),請各位笑納。
概念:
1.指令集:cpu能夠執(zhí)行的指令的集合。
2.指令:cpu所能夠執(zhí)行的操作。
3.操作數(shù):參加指令運(yùn)算的數(shù)據(jù)。
4.尋址方式:在指令中得到操作數(shù)的方式。
現(xiàn)在就重點(diǎn)討論尋址方式,說白了也就是cpu怎么樣從指令中得到操作數(shù)的問題。另外再強(qiáng)調(diào)一點(diǎn)操作數(shù)還分種類:
1)數(shù)據(jù)操作數(shù):全都是在指令當(dāng)中參加操作的數(shù)據(jù)。
1.立即操作數(shù):它在指令中直接給出。
2.寄存器操作數(shù):它被放到寄存器中。
3.存儲器操作數(shù):當(dāng)然在存儲器也就是內(nèi)存中。
4.i/o操作數(shù):它在你給出的i/o端口中。
2)轉(zhuǎn)移地址操作數(shù):在指令當(dāng)中不是參加運(yùn)算或被處理的數(shù)據(jù)了,而是轉(zhuǎn)移地址。
還可以按照下面分類方式:
1)源操作數(shù)src
2)目的操作數(shù)dst
源操作數(shù)都是指令當(dāng)中的第2個操作數(shù),在執(zhí)行完指令后操作數(shù)不變。而目的操作數(shù)是指令當(dāng)中的第1個操作數(shù),在執(zhí)行完操作指令后被新的數(shù)據(jù)替代。
我們就圍繞這幾種操作數(shù),也就是操作數(shù)所在的位置展開討論。
先說數(shù)據(jù)操作數(shù),它分3大類共7種。
1)立即數(shù)尋址方式:是針對立即操作數(shù)的尋址方式。在指令當(dāng)中直接給出,它根本就不用尋址。
例1:mov ax,1234h
mov [bx],5678h
在這里1234h和5678h都是立即操作數(shù),在指令當(dāng)中直接給出。
2)寄存器尋址方式:是針對寄存器操作數(shù)的尋址方式,它在寄存器中我們就用這中方式來找到它。
例2:mov bx,ax
mov bp,[si]
在這里ax,bx,ds都算是寄存器尋址,例1中的ax也是寄存器尋址方式。
3)存儲器尋址方式:針對在內(nèi)存中的數(shù)據(jù)(存儲器操作數(shù))都用這種方式來尋找,一共有5種(這是我自己的說法,便于記憶)。
不得不提及以下的概念:由于8086/8088的字長是16bit,能夠直接尋址2的16次方也就是64kb,而地址總線是20bit,能夠直接尋址2的20次方也就是1M空間,所以把內(nèi)存分為若干個段,每個段最小16byte(被稱為小節(jié)),最大64kb,它們之間可以相互重疊,這樣一來內(nèi)存就被分成以16byte為單元的64k小節(jié),cpu就以1小節(jié)為單位尋址:在段寄存器中給出段地址(16bit),在指令當(dāng)中給出段內(nèi)偏移地址(16bit),然后把段地址左移4bit再與偏移地址求和就得到數(shù)據(jù)在內(nèi)存當(dāng)中的實(shí)際物理地址了,因而可以找到數(shù)據(jù)。
1.存儲器直接尋址方式:在指令當(dāng)中以 [地址] 的方式直接給出數(shù)據(jù)所在內(nèi)存段的偏移地址。
例3:mov ax,es:[1234h]
mov dx,VALUE
mov dx,[VALUE]
在這里[1234h]和VALUE就是在指令中直接給出的數(shù)據(jù)所在內(nèi)存段的偏移地址(16bit)。
VALUE是符號地址,是用偽指令來定義的,它代表一個在內(nèi)存中的數(shù)據(jù)(也就是它的名字)。es:是段前綴符,用來指出段地址,在這之前應(yīng)該將段地址添入段中,本例中是es,默認(rèn)是ds,也就是不需給出。應(yīng)該注意 [地址] 與立即尋址的區(qū)別,在直接給出的數(shù)據(jù)兩邊加 [] 表示存儲器直接尋址,以區(qū)別立即尋址。另外 VALUE=[VALUE]。
2.寄存器間接尋址:不是在指令中直接給出數(shù)據(jù)在內(nèi)存中的偏移地址,而是把偏移地址放到了寄存器中。
例4:mov ax,[bx]
這里[bx]就是寄存器間接尋址,bx中應(yīng)方入段內(nèi)偏移地址。其中:若使用bx,si,di默認(rèn)段地址為ds,若使用bp則默認(rèn)段地址為ss,并且允許段跨越,也就是加段前綴符。注意:在寄存器兩邊加 [] 以與寄存器尋址區(qū)別。
3.寄存器間接相對尋址:偏移地址是bx,bp,si,di中的內(nèi)容再與一個8bit或16bit 的位移量之和。
例5:mov ax,[bx]+12h
mov ax,[si]+5678h
mov ax,[bp]+1234h
在這里[bx]+12h,[si]+5678h,[bp]+1234h都是寄存器間接相對尋址。12h是8bit位移量,1234h和5678h是16bit位移量。若使用bx,si,di則默認(rèn)段寄存器是ds,若使用bp則默認(rèn)段寄存器是ss,并且允許段跨越。
4.基址變址尋址:偏移地址是一個基址寄存器和一個變址寄存器內(nèi)容的和,既:bx或bp中的一個與si或di中的一個求和而得到。
例6:mov ax,[bx+si]
mov ax,[bp+di]
上面[bx+si]和[bp+di]都是基址變址尋址。若使用bx做基址寄存器則默認(rèn)段地址為ds,若使用bp為基址寄存器則默認(rèn)段為ss,允許段跨越。
5.基址變址相對尋址:偏移量是一個基址寄存器一個變址寄存器只和再與一個8bit或一個16bit位移量只和得到。
例7:mov ax,[bx+si]+12h
mov ax,[bp+di]+1234h
[bx+si]+12h和[bp+di]+1234h就是基址變址相對尋址。若使用bx做基址寄存器則默認(rèn)段是ds,若使用bp做基址寄存器則默認(rèn)段為ss。允許段跨越。

下面是轉(zhuǎn)移地址操作數(shù)的尋址方式:
1)段內(nèi)直接轉(zhuǎn)移
1.段內(nèi)直接短轉(zhuǎn)移:cs(代碼段)內(nèi)容不變,而ip(指令指針寄存器)內(nèi)容由當(dāng)前ip內(nèi)容+(-127~127),在指令中直接給出。
例8:jmp short SHORT_NEW_ADDR
其中,short是段內(nèi)短轉(zhuǎn)移的操作符,用以指出是轉(zhuǎn)移到當(dāng)前位置前后不超過±127字節(jié)的地方。而NEW_ADDR是要轉(zhuǎn)移到的符號地址,它的位置應(yīng)該在當(dāng)前ip指針?biāo)谄频刂凡怀^
±127的地方。否則語法出錯。
2.段內(nèi)直接近轉(zhuǎn)移:cs內(nèi)容不變,而ip內(nèi)容由當(dāng)前ip內(nèi)容+(-32767~32767),在指令中直接給出。
例9:jmp near ptr NEAR_NEW_ADDR
其中near ptr是段內(nèi)近轉(zhuǎn)移的操作符,用以指出轉(zhuǎn)移到當(dāng)前位置前后不超過±32767的地方。NEAR_NEW_ADDR是要轉(zhuǎn)移到的符號地址。
2)段內(nèi)間接轉(zhuǎn)移:cs的內(nèi)容不變,而ip的內(nèi)容放在寄存器中或者存儲器中給出。
例10:jmp bx
jmp word ptr [bx]+1234h
這種尋址方式是在寄存器或存儲器中找到要轉(zhuǎn)移到的地址,而地址是16bit的,因而寄存器必須為16bit,如:bx,我們用word ptr來指定存儲器單元也是16bit的。注意:它是間接的給出,只能使用類似于數(shù)據(jù)操作數(shù)中的除立即尋址以外的6種尋址方式(就在上面)。
3)段間直接尋址:cs和ip的內(nèi)容全都變化,由指令當(dāng)中直接給出要轉(zhuǎn)移到的某一個段內(nèi)的某一個偏移地址處。
例11:jmp 1234h:5678h
jmp far ptr NEW_ADDR
1234h送入cs中作為新的段地址,5678h送入ip中作為新的偏移地址。far ptr是段間直接轉(zhuǎn)移操作符,NEW_ADDR是另外一個段內(nèi)的偏移地址,在這個指令中把NEW_ADDR的段地址送入cs(不用你給出),把它的段內(nèi)偏移地址送入ip中作為新的偏移地址。
4)段間間接尋址:cs和ip的內(nèi)容全變化,由指令當(dāng)中給出的一個4字節(jié)連續(xù)存儲單元,其中低2字節(jié)送入ip作為偏移地址,高2字節(jié)送入cs作為段地址。
例12:jmp dword ptr [bx][si]+1234h
jmp dword ptr [1234h]
jmp dword ptr [si]
dword ptr是雙字(4個字節(jié)連續(xù)存儲單元)操作符,用來指出下面的存儲單元是4個字節(jié)的。由于它是4個字節(jié)的,所以只能使用類似于數(shù)據(jù)操作數(shù)中的存儲器尋址方式(共5種,還記得嗎?)。

另外作為特殊的尋址方式還有三種:I/O尋址,串尋址,隱含尋址。它們都分別針對I/O指令,串操作指令以及無操作數(shù)的指令,而且都比較簡單,讀者自行總結(jié)。

到此為止說明了8086/8088cpu中的所有尋址方式,我這里只是個總結(jié),具體的細(xì)節(jié)還要大家自己鉆研課本,才能理解。
寫的有些倉促可能有些遺漏或錯誤,還請諒解。

總結(jié)

以上所述是小編給大家介紹的匯編語言入門教程,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對html5模板網(wǎng)網(wǎng)站的支持!
如果你覺得本文對你有幫助,歡迎轉(zhuǎn)載,煩請注明出處,謝謝!

【網(wǎng)站聲明】本站部分內(nèi)容來源于互聯(lián)網(wǎng),旨在幫助大家更快的解決問題,如果有圖片或者內(nèi)容侵犯了您的權(quán)益,請聯(lián)系我們刪除處理,感謝您的支持!

相關(guān)文檔推薦

這篇文章主要介紹了匯編語言 寄存器內(nèi)存訪問原理解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
這篇文章主要介紹了使用匯編語言實(shí)現(xiàn)if else 循環(huán)函數(shù)調(diào)用的具體方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編
這篇文章主要介紹了匯編語言位向量(位映射)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)
這篇文章主要介紹了匯編語言AND指令實(shí)現(xiàn)對兩個操作數(shù)進(jìn)行邏輯(按位)與操作,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面
在匯編語言中,MOV指令是數(shù)據(jù)傳送指令,也是最基本的編程指令,這篇文章主要介紹了匯編語言MOV指令,需要的朋友可以參考下
主站蜘蛛池模板: 欧美日韩专区 | 在线中文字幕av | 日韩精品免费在线观看 | 亚洲成人一区二区 | 欧美一页| 国产成人精品一区二 | 免费a网站 | 成人欧美一区二区三区黑人孕妇 | 国产一区 | 男女羞羞视频在线免费观看 | 黄网站涩免费蜜桃网站 | 久久精品欧美一区二区三区不卡 | 中文字幕免费中文 | 国产欧美综合在线 | 精品国产31久久久久久 | 欧美日韩亚洲成人 | 亚洲一级淫片 | 中文在线观看视频 | 日韩国产中文字幕 | 网站黄色在线 | 日韩精品 电影一区 亚洲 | 国产 日韩 欧美 在线 | 羞羞色网站| 欧美在线成人影院 | 日本精品一区二区三区视频 | 久久精品国产精品青草 | 欧美寡妇偷汉性猛交 | 秋霞在线一区 | 国产午夜精品一区二区三区嫩草 | 成人网址在线观看 | 日韩精品在线观看免费 | 成人av免费播放 | 日韩一级不卡 | 九九九久久国产免费 | 一区二区成人 | 国产精品99久久久久久久久久久久 | 欧美激情精品久久久久久免费 | 国产精品欧美一区喷水 | 亚洲网在线 | 青青久久| 91精品国产乱码麻豆白嫩 |