1. 匯編指令詳解
MOV(MOVe) 傳送指令
PUSH 入棧指令
POP 出棧指令
XCHG(eXCHanG) 交換指令
XLAT(TRANSLATE) 換碼指令
LEA (Load Effective Address) 有效地址送寄存器指令
LDS(Load DS with pointer) 指針送寄存器和DS指令
LES(Load ES with pointer) 指針送寄存器和ES指令
LAHF(Load AH with Flags) 標志位送AH指令
SAHF(Store AH into Flgs) AH送標志寄存器指令
ADD 加法指令
ADC 帶進位加法指令
INC 加1指令
SUB(SUBtract) 不帶借位的減法指令
SBB(SuVtrach with borrow) 帶借位的減法指令
DEC(DECrement) 減1指領
NEG(NEGate) 求補指令
CMP(CoMPare) 比較指令
MUL(unsinged MULtiple) 無符號數乘法指令
IMUL(sIgned MUL tiple) 有符號數乘法指令
DIV(unsigned DIVide) 無符號數除法指令
IDIV(sIgned DIVide) 有符號數除法指令
DAA 壓縮的BCD碼加法十進制調整指令
DAS 壓縮的BCD碼減法十進制調整指令
AAA 非壓縮的BCD碼加法十進制調整指令
AAS 非壓縮的BCD碼加法十進制調整指令
AND 邏輯與指令
OR 邏輯或指令
XOR 邏輯異或指令
NOT 邏輯非指令
TEST 測試指令
SHL(SHift logical Letf) 邏輯左移指令
SHR(SHift logical Right) 邏輯右移指令
ROL(Rotate Left ) 循環左移指令
ROR(Rotate Right) 循環右移指令
RCL(Rotate Left through Carry) 帶進位循環左移
RCR(Rotate Right through Carry) 帶進位循環左移
MOVS(MOVe String) 串傳送指令
REP(REPeat) 重復操作前綴
CLD(CLear Direction flag) 清除方向標志指令
STD(SeT Direction flag) 設置方向標志指令
CMPS(CoMPare String) 串比較指令
SCAS(SCAn String) 串掃描指令
REPE/REPZ(REPeat while Equal/Zero)相等/為零時重復操作前綴
REPNE/REPNZ(REPeat while Not Equal/Zero)不相等/不為零進重復前綴
JMP(JuMP) 無條件轉移指令
JZ,JNZ,JS,JNS,JO,JNO,JP,JNP,JB,JNB,JBE,JNBE,JL,JNL,JLE,JNLE,JCXZ 條件轉移指令
LOOP 循環指令P70
LOOPZ/LOOPE 為零/相等時循環指令
LOOPNZ/LOOPNE 不為零/不相等時循環指令
CALL 子程序調用指令
RET(RETun) 子程序返回指令
NOP(No OPeretion) 無操作指令
HLT(HaLT) 停機指令
OFFSET 返回偏移地址
SEG 返回段地址
EQU(=) 等值語句
DUP 操作數欄位用復制操作符
SEGMENT,ENDS 段定義指令
ASSUME 段地址分配指令
ORG 起始偏移地址設置指令
$ 地址計數器的當前值
PROC,ENDP 過程定義語句
NAME,TITLE,END 程序開始結束語句
MACRO,ENDM 宏定義指令
2. 如何將es5的代碼轉換為es6
在這里需要的環境就是node,可以去查一下安裝教程,這里就不贅述了。當然需要我們的主角--webpack,很強大的一個工具。
安裝webpack:(cmd命令窗口,也可以用git)
a.安裝webpack到全局 npm install webpack -g
b.然後安裝webpack到你的項目中(要切盤到你的目錄下) npm install webpack --save-dev
c.webpack中常用命令webpack --watch 只要改變了jsx內容,直接將改變的內容重新編譯打包,運行久了以後會自動終止
安裝完成後需要下面的插件(切盤到你的項目下):
1.npm install babel-core --save-dev
2.npm install babel-loader --save-dev 下載載入器
3.npm install babel-preset-es2015 --save-dev
逐步下載上述插件,完成之後創建一個webpack.config.js文件放在你的項目目錄下,在裡面寫配置文件,代碼如下:
mole.exports={
//文件入口
entry: {
main: './es6/main.js',
common: './es6/common.js'
},
//文件出口
output:{
path:'./js',
filename:'[name].bundle.js'
},
//引入模塊。babel-loader轉換
mole:{
loaders:[
{
test: /\.js$/,
exclude: /node_moles/,
loader: "babel-loader",
query:
{
presets: ['es2015'], //並不明白,這么寫就對了,如果用react,就在這里寫上['react']
//npm install babel-plugin-transform-runtime 然後引入 解決es6生成器函數帶來的問題
}
}
]
}
}
ok,完成。
3. Elasticsearch性能優化
註:文本整理自《ELKstack權威指南》
在 CRUD 章節,我們已經知道 ES 的數據寫入是如何操作的了。喜歡自己動手的讀者可能已經迫不及待的自己寫了程序開始往 ES 里寫數據做測試。這時候大家會發現:程序的運行速度非常一般,即使 ES 服務運行在本機,一秒鍾大概也就能寫入幾百條數據。
這種速度顯然不是 ES 的極限。事實上,每條數據經過一次完整的 HTTP POST 請求和 ES indexing 是一種極大的性能浪費,為此,ES 設計了批量提交方式。在數據讀取方面,叫 mget 介面,在數據變更方面,叫 bulk 介面。mget 一般常用於搜索時 ES 節點之間批量獲取中間結果集,對於 Elastic Stack 用戶,更常見到的是 bulk 介面。
bulk 介面採用一種比較簡朴的數據積累格式,示例如下:
格式是,每條 JSON 數據的上面,加一行描述性的元 JSON,指明下一行數據的操作類型,歸屬索引信息等。
採用這種格式,而不是一般的 JSON 數組格式,是因為接收到 bulk 請求的 ES 節點,就可以不需要做完整的 JSON 數組解析處理,直接按行處理簡短的元 JSON,就可以確定下一行數據 JSON 轉發給哪個數據節點了。這樣,一個固定內存大小的 network buffer 空間,就可以反復使用,又節省了大量 JVM 的 GC。
事實上,產品級的 logstash、rsyslog、spark 都是默認採用 bulk 介面進行數據寫入的。對於打算自己寫程序的讀者,建議採用 Perl 的 Search::Elasticsearch::Bulk 或者 Python 的 elasticsearch.helpers.* 庫。
在配置 bulk 數據的時候,一般需要注意的就是請求體大小(bulk size)。
這里有一點細節上的矛盾,我們知道,HTTP 請求,是可以通過 HTTP 狀態碼 100 Continue 來持續發送數據的。但對於 ES 節點接收 HTTP 請求體的 Content-Length 來說,是按照整個大小來計算的。所以,首先,要確保 bulk 數據不要超過 http.max_content_length 設置。
那麼,是不是盡量讓 bulk size 接近這個數值呢?當然不是。
依然是請求體的問題,因為請求體需要全部載入到內存,而 JVM Heap 一共就那麼多(按 31GB 算),過大的請求體,會擠占其他線程池的空間,反而導致寫入性能的下降。
再考慮網卡流量,磁碟轉速的問題,所以一般來說,建議 bulk 請求體的大小,在 15MB 左右,通過實際測試繼續向上探索最合適的設置。
注意:這里說的 15MB 是請求體的位元組數,而不是程序里里設置的 bulk size。bulk size 一般指數據的條目數。不要忘了,bulk 請求體中,每條數據還會額外帶上一行元 JSON。
以 logstash 默認的 bulk_size => 5000 為例,假設單條數據平均大小 200B ,一次 bulk 請求體的大小就是 1.5MB。那麼我們可以嘗試 bulk_size => 50000 ;而如果單條數據平均大小是 20KB,一次 bulk 大小就是 100MB,顯然超標了,需要嘗試下調至 bulk_size => 500 。
gateway 是 ES 設計用來長期存儲索引數據的介面。一般來說,大家都是用本地磁碟來存儲索引數據,即 gateway.type 為 local 。
數據恢復中,有很多策略調整我們已經在之前分片控制小節講過。除開分片級別的控制以外,gateway 級別也還有一些可優化的地方:
注意:gateway 中說的節點,僅包括主節點和數據節點,純粹的 client 節點是不算在內的。如果你有更明確的選擇,也可以按需求寫:
雖然 ES 對 gateway 使用 NFS,iscsi 等共享存儲的方式極力反對,但是對於較大量級的索引的副本數據,ES 從 1.5 版本開始,還是提供了一種節約成本又不特別影響性能的方式:影子副本(shadow replica)。
首先,需要在集群各節點的 elasticsearch.yml 中開啟選項:
同時,確保各節點使用相同的路徑掛載了共享存儲,且目錄許可權為 Elasticsearch 進程用戶可讀可寫。
然後,創建索引:
針對 shadow replicas ,ES 節點不會做實際的索引操作,而是單純的每次 flush 時,把 segment 內容 fsync 到共享存儲磁碟上。然後 refresh 讓其他節點能夠搜索該 segment 內容。
如果你已經決定把數據放到共享存儲上了,採用 shadow replicas 還是有一些好處的:
但是請注意:主分片節點還是要承擔一個副本的寫入過程,並不像 Lucene 的 FileReplicator 那樣通過復制文件完成,所以達不到完全節省 CPU 的效果。
shadow replicas 只是一個在某些特定環境下有用的方式。在資源允許的情況下,還是應該使用 local gateway。而另外採用 snapshot 介面來完成數據長期備份到 HDFS 或其他共享存儲的需要。
我們都知道,ES 中的 master 跟一般 MySQL、Hadoop 的 master 是不一樣的。它即不是寫入流量的唯一入口,也不是所有數據的元信息的存放地點。所以,一般來說,ES 的 master 節點負載很輕,集群性能是可以近似認為隨著 data 節點的擴展線性提升的。
但是,上面這句話並不是完全正確的。
ES 中有一件事情是只有 master 節點能管理的,這就是集群狀態(cluster state)。
集群狀態中包括以下信息:
這些信息在集群的任意節點上都存放著,你也可以通過 /_cluster/state 介面直接讀取到其內容。注意這最後一項信息,之前我們已經講過 ES 怎麼通過簡單地取余知道一條數據放在哪個分片里,加上現在集群狀態里又記載了分片在哪個節點上,那麼,整個集群里,任意節點都可以知道一條數據在哪個節點上存儲了。所以,數據讀寫才可以發送給集群里任意節點。
至於修改,則只能由 master 節點完成!顯然,集群狀態里大部分內容是極少變動的,唯獨有一樣除外——索引的映射。因為 ES 的 schema-less 特性,我們可以任意寫入 JSON 數據,所以索引中隨時可能增加新的欄位。這個時候,負責容納這條數據的主分片所在的節點,會暫停寫入操作,將欄位的映射結果傳遞給 master 節點;master 節點合並這段修改到集群狀態里,發送新版本的集群狀態到集群的所有節點上。然後寫入操作才會繼續。一般來說,這個操作是在一二十毫秒內就可以完成,影響也不大。
但是也有一些情況會是例外。
在較大規模的 Elastic Stack 應用場景中,這是比較常見的一個情況。因為 Elastic Stack 建議採用日期時間作為索引的劃分方式,所以定時(一般是每天),會統一產生一批新的索引。而前面已經講過,ES 的集群狀態每次更新都是阻塞式的發布到全部節點上以後,節點才能繼續後續處理。
這就意味著,如果在集群負載較高的時候,批量新建新索引,可能會有一個顯著的阻塞時間,無法寫入任何數據。要等到全部節點同步完成集群狀態以後,數據寫入才能恢復。
不巧的是,中國使用的是北京時間,UTC +0800。也就是說,默認的 Elastic Stack 新建索引時間是在早上 8 點。這個時間點一般日誌寫入量已經上漲到一定水平了(當然,晚上 0 點的量其實也不低)。
對此,可以通過定時任務,每天在最低谷的早上三四點,提前通過 POST mapping 的方式,創建好之後幾天的索引。就可以避免這個問題了。
如果你的日誌是比較嚴重的非結構化數據,這個問題在 2.0 版本後會變得更加嚴重。 Elasticsearch 從 2.0 版本開始,對 mapping 更新做了重構。為了防止欄位類型沖突和減少 master 定期下發全量 cluster state 導致的大流量壓力,新的實現和舊實現的區別在:
也就是說,一旦你日誌中欄位數量較多,在新創建索引的一段時間內,可能長達幾十分鍾一直被反復鎖死!
這是另一種常見的濫用。在使用 Elastic Stack 處理訪問日誌時,為了查詢更方便,可能會採用 logstash-filter-kv 插件,將訪問日誌中的每個 URL 參數,都切分成單獨的欄位。比如一個 "/index.do?uid=1234567890&action=payload" 的 URL 會被轉換成如下 JSON:
但是,因為集群狀態是存在所有節點的內存里的,一旦 URL 參數過多,ES 節點的內存就被大量用於存儲欄位映射內容。這是一個極大的浪費。如果碰上 URL 參數的鍵內容本身一直在變動,直接撐爆 ES 內存都是有可能的!
以上是真實發生的事件,開發人員莫名的選擇將一個 UUID 結果作為 key 放在 URL 參數里。直接導致 ES 集群 master 節點全部 OOM。
如果你在 ES 日誌中一直看到有新的 updating mapping [logstash-2015.06.01] 字樣出現的話,請鄭重考慮一下自己是不是用的上如此細分的欄位列表吧。
好,三秒鍾過去,如果你確定一定以及肯定還要這么做,下面是一個變通的解決辦法。
用 nested object 來存放 URL 參數的方法稍微復雜,但還可以接受。單從 JSON 數據層面看,新方式的數據結構如下:
沒錯,看起來就是一個數組。但是 JSON 數組在 ES 里是有兩種處理方式的。
如果直接寫入數組,ES 在實際索引過程中,會把所有內容都平鋪開,變成 Arrays of Inner Objects 。整條數據實際類似這樣的結構:
這種方式最大的問題是,當你採用 urlargs.key:"uid" AND urlargs.value:"0987654321" 語句意圖搜索一個 uid=0987654321 的請求時,實際是整個 URL 參數中任意一處 value 為 0987654321 的,都會命中。
要想達到正確搜索的目的,需要在寫入數據之前,指定 urlargs 欄位的映射類型為 nested object。命令如下:
這樣,數據實際是類似這樣的結構:
當然,nested object 節省欄位映射的優勢對應的是它在使用的復雜。Query 和 Aggs 都必須使用專門的 nested query 和 nested aggs 才能正確讀取到它。
nested query 語法如下:
nested aggs 語法如下:
ES 內針對不同階段,設計有不同的緩存。以此提升數據檢索時的響應性能。主要包括節點層面的 filter cache 和分片層面的 request cache。下面分別講述。
ES 的 query DSL 在 2.0 版本之前分為 query 和 filter 兩種,很多檢索語法,是同時存在 query 和 filter 里的。比如最常用的 term、prefix、range 等。怎麼選擇是使用 query 還是 filter 成為很多用戶頭疼的難題。於是從 2.0 版本開始,ES 乾脆合並了 filter 統一歸為 query。但是具體的檢索語法本身,依然有 query 和 filter 上下文的區別。ES 依靠這個上下文判斷,來自動決定是否啟用 filter cache。
query 跟 filter 上下文的區別,簡單來說:
所以,選擇也就出來了:
不過我們要怎麼寫,才能讓 ES 正確判斷呢?看下面這個請求:
在這個請求中,
需要注意的是,filter cache 是節點層面的緩存設置,每個節點上所有數據在響應請求時,是共用一個緩存空間的。當空間用滿,按照 LRU 策略淘汰掉最冷的數據。
可以用 indices.cache.filter.size 配置來設置這個緩存空間的大小,默認是 JVM 堆的 10%,也可以設置一個絕對值。注意這是一個靜態值,必須在 elasticsearch.yml 中提前配置。
ES 還有另一個分片層面的緩存,叫 shard request cache。5.0 之前的版本中,request cache 的用途並不大,因為 query cache 要起作用,還有幾個先決條件:
以 Elastic Stack 場景來說,Kibana 里幾乎所有的請求,都是有 @timestamp 作為過濾條件的,而且大多數是以 最近 N 小時/分鍾 這樣的選項,也就是說,頁面每次刷新,發出的請求 JSON 里的時間過濾部分都是在變動的。query cache 在處理 Kibana 發出的請求時,完全無用。
而 5.0 版本的一大特性,叫 instant aggregation。解決了這個先決條件的一大阻礙。
在之前的版本,Elasticsearch 接收到請求之後,直接把請求原樣轉發給各分片,由各分片所在的節點自行完成請求的解析,進行實際的搜索操作。所以緩存的鍵是原始 JSON 串。
而 5.0 的重構後,接收到請求的節點先把請求的解析做完,發送到各節點的是統一拆分修改好的請求,這樣就不再擔心 JSON 串多個空格啥的了。
其次,上面說的『拆分修改』是怎麼回事呢?
比如,我們在 Kibana 里搜索一個最近 7 天( @timestamp:["now-7d" TO "now"] )的數據,ES 就可以根據按天索引的判斷,知道從 6 天前到昨天這 5 個索引是肯定全覆蓋的。那麼這個橫跨 7 天的 date range query 就變成了 5 個 match_all query 加 2 個短時間的 date_range query。
現在你的儀表盤過 5 分鍾自動刷新一次,再提交上來一次最近 7 天的請求,中間這 5 個 match_all 就完全一樣了,直接從 request cache 返回即可,需要重新請求的,只有兩頭真正在變動的 date_range 了。
注1: match_all 不用遍歷倒排索引,比直接查詢 @timestamp:* 要快很多。
注2:判斷覆蓋修改為 match_all 並不是真的按照索引名稱,而是 ES 從 2.x 開始提供的 field_stats 介面可以直接獲取到 @timestamp 在本索引內的 max/min 值。當然從概念上如此理解也是可以接受的。
響應結果如下:
和 filter cache 一樣,request cache 的大小也是以節點級別控制的,配置項名為 indices.requests.cache.size ,其默認值為 1% 。
欄位數據(fielddata),在 Lucene 中又叫 uninverted index。我們都知道,搜索引擎會使用倒排索引(inverted index)來映射單詞到文檔的 ID 號。而同時,為了提供對文檔內容的聚合,Lucene 還可以在運行時將每個欄位的單詞以字典序排成另一個 uninverted index,可以大大加速計算性能。
作為一個加速性能的方式,fielddata 當然是被全部載入在內存的時候最為有效。這也是 ES 默認的運行設置。但是,內存是有限的,所以 ES 同時也需要提供對 fielddata 內存的限額方式:
Elasticsearch 在 total,fielddata,request 三個層面上都設計有 circuit breaker 以保護進程不至於發生 OOM 事件。在 fielddata 層面,其設置為:
但是相比較集群龐大的數據量,內存本身是遠遠不夠的。為了解決這個問題,ES 引入了另一個特性,可以對精確索引的欄位,指定 fielddata 的存儲方式。這個配置項叫: doc_values 。
所謂 doc_values ,其實就是在 ES 將數據寫入索引的時候,提前生成好 fielddata 內容,並記錄到磁碟上。因為 fielddata 數據是順序讀寫的,所以即使在磁碟上,通過文件系統層的緩存,也可以獲得相當不錯的性能。
注意:因為 doc_values 是在數據寫入時即生成內容,所以,它只能應用在精準索引的欄位上,因為索引進程沒法知道後續會有什麼分詞器生成的結果。
由於在 Elastic Stack 場景中, doc_values 的使用極其頻繁,到 Elasticsearch 5.0 以後,這兩者的區別被徹底強化成兩個不同欄位類型: text 和 keyword 。
等同於過去的:
而
等同於過去的:
也就是說,以後的用戶,已經不太需要在意 fielddata 的問題了。不過依然有少數情況,你會需要對分詞欄位做聚合統計的話,你可以在自己接受范圍內,開啟這個特性:
你可以看到在上面加了一段 fielddata_frequency_filter 配置,這個配置是 segment 級別的。上面示例的意思是:只有這個 segment 里的文檔數量超過 500 個,而且含有該欄位的文檔數量占該 segment 里的文檔數量比例超過 10% 時,才載入這個 segment 的 fielddata。
下面是一個可能有用的對分詞欄位做聚合的示例:
這個示例可以對經過了 logstash-filter-punct 插件處理的數據,獲取每種 punct 類型日誌的關鍵詞和對應的代表性日誌原文。其效果類似 Splunk 的事件模式功能:
[圖片上傳失敗...(image-b0b69f-1511752650964)]
如果經過之前章節的一系列優化之後,數據確實超過了集群能承載的能力,除了拆分集群以外,最後就只剩下一個辦法了:清除廢舊索引。
為了更加方便的做清除數據,合並 segment,備份恢復等管理任務,Elasticsearch 在提供相關 API 的同時,另外准備了一個命令行工具,叫 curator 。curator 是 Python 程序,可以直接通過 pypi 庫安裝:
注意,是 elasticsearch-curator 不是 curator。PyPi 原先就有另一個項目叫這個名字
和 Elastic Stack 里其他組件一樣,curator 也是被 Elastic.co 收購的原開源社區周邊。收編之後同樣進行了一次重構,命令行參數從單字母風格改成了長單詞風格。新版本的 curator 命令可用參數如下:
Options 包括:
--host TEXT Elasticsearch host.
--url_prefix TEXT Elasticsearch http url prefix.
--port INTEGER Elasticsearch port.
--use_ssl Connect to Elasticsearch through SSL.
--http_auth TEXT Use Basic Authentication ex: user:pass
--timeout INTEGER Connection timeout in seconds.
--master-only Only operate on elected master node.
--dry-run Do not perform any changes.
--debug Debug mode
--loglevel TEXT Log level
--logfile TEXT log file
--logformat TEXT Log output format [default|logstash].
--version Show the version and exit.
--help Show this message and exit.
Commands 包括:
alias Index Aliasing
allocation Index Allocation
bloom Disable bloom filter cache
close Close indices
delete Delete indices or snapshots
open Open indices
optimize Optimize Indices
replicas Replica Count Per-shard
show Show indices or snapshots
snapshot Take snapshots of indices (Backup)
針對具體的 Command,還可以繼續使用 --help 查看該子命令的幫助。比如查看 close 子命令的幫助,輸入 curator close --help ,結果如下:
在使用 1.4.0 以上版本的 Elasticsearch 前提下,curator 曾經主要的一個子命令 bloom 已經不再需要使用。所以,目前最常用的三個子命令,分別是 close , delete 和 optimize ,示例如下:
這一頓任務,結果是:
logstash-mweibo-nginx-yyyy.mm.dd 索引保存最近 5 天, logstash-mweibo-client-yyyy.mm.dd 保存最近 10 天, logstash-mweibo-yyyy.mm.dd 索引保存最近 30 天;且所有七天前的 logstash-* 索引都暫時關閉不用;最後對所有非當日日誌做 segment 合並優化。
profiler 是 Elasticsearch 5.0 的一個新介面。通過這個功能,可以看到一個搜索聚合請求,是如何拆分成底層的 Lucene 請求,並且顯示每部分的耗時情況。
啟用 profiler 的方式很簡單,直接在請求里加一行即可:
可以看到其中對 query 和 aggs 部分的返回是不太一樣的。
query 部分包括 collectors、rewrite 和 query 部分。對復雜 query,profiler 會拆分 query 成多個基礎的 TermQuery,然後每個 TermQuery 再顯示各自的分階段耗時如下:
我們可以很明顯的看到聚合統計在初始化階段、收集階段、構建階段、匯總階段分別花了多少時間,遍歷了多少數據。
注意其中 rece 階段還沒實現完畢,所有都是 0。因為目前 profiler 只能在 shard 級別上做統計。
collect 階段的耗時,有助於我們調整對應 aggs 的 collect_mode 參數選擇。目前 Elasticsearch 支持 breadth_first 和 depth_first 兩種方式。
initialise 階段的耗時,有助於我們調整對應 aggs 的 execution_hint 參數選擇。目前 Elasticsearch 支持 map 、 global_ordinals_low_cardinality 、 global_ordinals 和 global_ordinals_hash 四種選擇。在計算離散度比較大的欄位統計值時,適當調整該參數,有益於節省內存和提高計算速度。
對高離散度欄位值統計性能很關注的讀者,可以關注 https://github.com/elastic/elasticsearch/pull/21626 這條記錄的進展。
(本文完)
文本整理自《ELKstack權威指南》
4. 匯編中的常見指令有哪些
匯編語言指令集
匯編指令是匯編語言中使用的一些操作符(如mov,inc,loop)和助記符,還包括一些偽指令(如assume,end)。用於告訴匯編程序如何進行匯編的指令,它既不控制機器的操作也不被匯編成機器代碼,只能為匯編程序所識別並指導匯編如何進行。
一、數據傳輸指令
它們在存貯器和寄存器、寄存器和輸入輸出埠之間傳送數據。
1. 通用數據傳送指令
MOV 傳送字或位元組.
MOVSX 先符號擴展,再傳送.
MOVZX 先零擴展,再傳送.
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位寄存器里位元組的順序
XCHG 交換字或位元組.( 至少有一個操作數為寄存器,段寄存器不可作為操作數)
CMPXCHG 比較並交換操作數.( 第二個操作數必須為累加器AL/AX/EAX )
XADD 先交換再累加.( 結果在第一個操作數里 )
XLAT 位元組查表轉換.
── BX 指向一張 256 位元組的表的起點, AL 為表的索引值 (0-255,即 0-FFH); 返回 AL 為查表結果. ( [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 傳送目標指針,把指針內容裝入DS. 例: LDS SI,string ;把段地址:偏移地址存到DS:SI.
LES 傳送目標指針,把指針內容裝入ES. 例: LES DI,string ;把段地址:偏移地址存到ES:DI.
LFS 傳送目標指針,把指針內容裝入FS. 例: LFS DI,string ;把段地址:偏移地址存到FS:DI.
LGS 傳送目標指針,把指針內容裝入GS. 例: LGS DI,string ;把段地址:偏移地址存到GS:DI.
LSS 傳送目標指針,把指針內容裝入SS. 例: LSS DI,string ;把段地址:偏移地址存到SS:DI.
4. 標志傳送指令.
LAHF 標志寄存器傳送,把標志裝入AH.
SAHF 標志寄存器傳送,把AH內容裝入標志寄存器.
PUSHF 標志入棧.
POPF 標志出棧.
PUSHD 32位標志入棧.
POPD 32位標志出棧.
二、算術運算指令
ADD 加法.
ADC 帶進位加法.
INC 加 1.
AAA 加法的ASCII碼調整.
DAA 加法的十進制調整.
SUB 減法.
SBB 帶借位減法.
DEC 減 1.
NEC 求反(以 0 減之).
CMP 比較.(兩操作數作減法,僅修改標志位,不回送結果).
AAS 減法的ASCII碼調整.
DAS 減法的十進制調整.
MUL 無符號乘法.
IMUL 整數乘法.
以上兩條,結果回送AH和AL(位元組運算),或DX和AX(字運算),
AAM 乘法的ASCII碼調整.
DIV 無符號除法.
IDIV 整數除法.
以上兩條,結果回送:
商回送AL,余數回送AH, (位元組運算);
或 商回送AX,余數回送DX, (字運算).
AAD 除法的ASCII碼調整.
CBW 位元組轉換為字. (把AL中位元組的符號擴展到AH中去)
CWD 字轉換為雙字. (把AX中的字的符號擴展到DX中去)
CWDE 字轉換為雙字. (把AX中的字元號擴展到EAX中去)
CDQ 雙字擴展. (把EAX中的字的符號擴展到EDX中去)
三、邏輯運算指令
AND 與運算.
or 或運算.
XOR 異或運算.
NOT 取反.
TEST 測試.(兩操作數作與運算,僅修改標志位,不回送結果).
SHL 邏輯左移.
SAL 算術左移.(=SHL)
SHR 邏輯右移.
SAR 算術右移.(=SHR)
ROL 循環左移.
ROR 循環右移.
RCL 通過進位的循環左移.
RCR 通過進位的循環右移.
以上八種移位指令,其移位次數可達255次.
移位一次時, 可直接用操作碼. 如 SHL AX,1.
移位>1次時, 則由寄存器CL給出移位次數.
如 MOV CL,04
SHL AX,CL
四、串指令
DS:SI 源串段寄存器 :源串變址.
ES:DI 目標串段寄存器:目標串變址.
CX 重復次數計數器.
AL/AX 掃描值.
D標志 0表示重復操作中SI和DI應自動增量; 1表示應自動減量.
Z標志 用來控制掃描或比較操作的結束.
MOVS 串傳送.
( MOVSB 傳送字元. MOVSW 傳送字. MOVSD 傳送雙字. )
CMPS 串比較.
( CMPSB 比較字元. CMPSW 比較字. )
SCAS 串掃描.
把AL或AX的內容與目標串作比較,比較結果反映在標志位.
LODS 裝入串.
把源串中的元素(字或位元組)逐一裝入AL或AX中.
( LODSB 傳送字元. LODSW 傳送字. LODSD 傳送雙字. )
STOS 保存串.
是LODS的逆過程.
REP 當CX/ECX<>0時重復.
REPE/REPZ 當ZF=1或比較結果相等,且CX/ECX<>0時重復.
REPNE/REPNZ 當ZF=0或比較結果不相等,且CX/ECX<>0時重復.
REPC 當CF=1且CX/ECX<>0時重復.
REPNC 當CF=0且CX/ECX<>0時重復.
五、程序轉移指令
1>無條件轉移指令 (長轉移)
JMP 無條件轉移指令
CALL 過程調用
RET/RETF過程返回.
2>條件轉移指令 (短轉移,-128到+127的距離內)
( 當且僅當(SF XOR OF)=1時,OP1<OP2 )
JA/JNBE 不小於或不等於時轉移.
JAE/JNB 大於或等於轉移.
JB/JNAE 小於轉移.
JBE/JNA 小於或等於轉移.
以上四條,測試無符號整數運算的結果(標志C和Z).
JG/JNLE 大於轉移.
JGE/JNL 大於或等於轉移.
JL/JNGE 小於轉移.
JLE/JNG 小於或等於轉移.
以上四條,測試帶符號整數運算的結果(標志S,O和Z).
JE/JZ 等於轉移.
JNE/JNZ 不等於時轉移.
JC 有進位時轉移.
JNC 無進位時轉移.
JNO 不溢出時轉移.
JNP/JPO 奇偶性為奇數時轉移.
JNS 符號位為 "0" 時轉移.
JO 溢出轉移.
JP/JPE 奇偶性為偶數時轉移.
JS 符號位為 "1" 時轉移.
3>循環控制指令(短轉移)
LOOP CX不為零時循環.
LOOPE/LOOPZ CX不為零且標志Z=1時循環.
LOOPNE/LOOPNZ CX不為零且標志Z=0時循環.
JCXZ CX為零時轉移.
JECXZ ECX為零時轉移.
4>中斷指令
INT 中斷指令
INTO 溢出中斷
IRET 中斷返回
5>處理器控制指令
HLT 處理器暫停, 直到出現中斷或復位信號才繼續.
WAIT 當晶元引線TEST為高電平時使CPU進入等待狀態.
ESC 轉換到外處理器.
LOCK 封鎖匯流排.
NOP 空操作.
STC 置進位標志位.
CLC 清進位標志位.
CMC 進位標志取反.
STD 置方向標志位.
CLD 清方向標志位.
STI 置中斷允許位.
CLI 清中斷允許位.
六、偽指令
DW 定義字(2位元組).
PROC 定義過程.
ENDP 過程結束.
SEGMENT 定義段.
ASSUME 建立段寄存器定址.
ENDS 段結束.
END 程序結束.
七、處理機控制指令:
標志處理指令 CLC(進位位置0指令)
CMC(進位位求反指令)
STC(進位位置為1指令)
CLD(方向標志置1指令)
STD(方向標志位置1指令)
CLI(中斷標志置0指令)
STI(中斷標志置1指令)
NOP(無操作)
HLT(停機)
WAIT(等待)
ESC(換碼)
LOCK(封鎖)
5. 求ETERM 基本操作的全部指令
查詢直達航班 的指令: AVH/HKGKUL12MARD/MH(AVH為固定格式,HKGKUL代表城市對(始發地和目的地)12MAR代表日期,D代表直達 MH代表指定航空公司)
建立航段組的指令: SD1L1(SD固定指令,前一個1代表航線序號,L代表艙位,後一個1代表人數(幾個人就是幾))
輸入姓名的指令: NM1姓名1姓名(NM為固定指令,前一個1是姓名前面必須加1,後一個1指增加一個人,可以同時增加至9個)
候補位置: SD1Y/LL1(SD和/LL為固定指令,前1為航段號,Y:艙位,後1為候補人數)
出票時限的指令: TKTL/1200/12AMR/SZX453 ( TKTL為固定指令.TKTL/時間/日期/訂座部門("."代表今天))
封口指令: 1. 2.i 3.KI (1.一般封口、2.強行封口、3.當候補機位成功變成KL狀態,輸入KI就會變成HK狀態)
定位時沒有封口需要:換名字 1/1 ZHOU/XUZHEN MR (用於只剩下最後1個位置的緊急情況)
輸入證件號碼的指令: SSR DOCS CX HK1 P/CN/G19307794/CN/25DEC80/M/15JAN19/JIN/XIAOYONG/P1 (SSR DOCS 航空公司 HK1 P/國籍/護照號碼/國籍/出生年月日/性別M男(F女)/護照有效期/姓/名/p1為固定格式.註:兒童和成人一樣的 方法;嬰兒票護照錄入和大人一樣只需在性別那一項:男嬰兒入MI,女嬰兒入FI)