8086指令系統概述
Intel 8086指令系統共有117條基本指令,可分成6個功能組
① 數據傳送類指令 :數據從哪里到哪里
② 算術運算類指令
③ 位操作類指令
④ 串操作類指令
⑤ 控制轉移類指令
⑥ 處理機控制類指令
數據傳送類指令
一丶通用數據傳送指令
1.MOV傳送指令

mov 指令傳送功能圖

請注意,立即數不能直接給段寄存器,都是通過中轉的
mov 注意事項
1.兩個操作數的類型不一致
例如源操作數是字節,目的操作數是字,或者是相反
mov al,050AH //錯誤 al是八位寄存器,只能接受八位,而這里是16位了
對於存儲器,和立即數同時都作為操作數的情況下,必須顯示的指明是什么類型
mov [2000h],12h //錯誤,應該寫成 mov byte ptr(或者word ptr)[2000h],12h
如果只是12h,則用byte ptr,當然你也可以寫成word ptr,但是修改內存的值修改后則是修改的兩個字節的長度
2.兩個操作數不能是存儲器
例如 mov [2000h],[2200h] 因為內存只是存儲的,傳送的結果要保存在寄存器當中,顯然內存沒有內置CPU,所以通過寄存器中轉,所以不能直接這樣
3.小心段操作寄存器
1
.立即數不能直接給段寄存器
mov ds,100
2
.不能直接改變cs段寄存器的值
mov cs,[si] 這條指令是可以編譯通過,但是運行的時候,因為你把代碼段的值改了,然后CS:IP確定的下一跳指令就會出錯,比如你的這條指令下面還有個mov ax,0 當你上面改了,那么mov ax,0 永遠不會執行,而你熟悉的改了cs的值可以,如果不熟悉那么代碼段就被破壞,程序就會執行崩潰.
3
.段寄存器和段寄存器不能直接數據傳送
mov ds,es
2.xchg交換指令
xchg reg/mem/accum , reg/mem/accum (accum指的是AL/AX/EAX)
其實就是寄存器的值交換,那么此時ax的值就是1,bx就是0
ax = 0 bx = 1 xchg ax,bx
有人說mov 指令也可以,確實是可以,但是指令周期不一樣,這個比mov指令快一個指令周期,而且還不浪費寄存器(否則需要三個寄存器完成交換)
寄存器和存儲器交換
xchg ax,[2000h] 字交換,ax正好可以放下16位,等價於 xchg [2000h],ax 這里會有人說為什么不用 word ptr說明一下,因為后面跟着的是16位寄存器,它默認就是 word ptr了xchg al,[2000h] 字節交換 ,等同於 xchg [2000h],al 同上為什么不用byte ptr
3.xlat 換碼指令(查表指令)
將
BX指定的緩沖區中,al執行的位移處的一個字節數據取出賦值給al,后面沒有操作數,默認操作數就是 BX和AL,直接 一個 xlat即可.,相當於數組尋址,bx放在數組首地址,al放下標。給設備做了一個表
改設備表,就相當於改了代碼
ary[]={0,0,0...96}//把65的ascii換為65 ary[65]
轉變成mov 相當於
mov al,ds:[bx+al]//注意這里是bx我草!!!!
就是dx數據里面有一塊完整的內存(比如是ASCII碼 a b c d),al 就給定一個下標,然后調用xlat指令,就可以根據al的下標獲取出來 abcd其中的一個ASCII碼重新放到al中,相當於數組尋址

第一步,使用e命令給400偏移處寫入 abcdefg的字符
第二步 使用 d命令查看

第三步開始匯編,先給bx賦值偏移量為400,則 DS:[DX]可以取得61(也就是a)的編碼,但是怎么取出來,要根據al給定的下標,比如al給了3,那么就是 DS:[DX+AL] 也就是取出63的編碼,賦值給al,我這里給的是0,所以下標取內容是61

4.PUSH,POP堆棧指令

SS代表棧的段地址,SP代表是棧頂 BP代表是棧底,堆棧的操作指令有兩種,第一種是PUSH壓棧,第二種是POP出棧
PUSH r16/m16/seg ;SP←SP-2 //第一步寄存器sp指針-2 ;SS:[SP]←r16/m16/seg //第二部把寄存器或主存或段寄存器壓入到棧
POP r16/m16/seg ;r16/m16/seg←SS:[SP] //第一步從棧中取出數據賦值給寄存器或主存或段寄存器 ;SP←SP+2 //第二部把寄存器sp指針+2
注意:棧結構是從高地址向低地址去使用
mov指令模擬push指令
第一步,要壓棧之前,sp需要-2,留出一個字的空間,這樣才可以把字壓入棧中
mov sp,bp 棧底和棧頂一樣 sup sp,2 棧頂-2留出兩個字節空間讓數據壓棧 mov bp sp, 讓新的棧頂指針位置賦值給棧底 mov word ptr [bp],1 棧底位置處壓入1
mov模擬pop出棧指令
mov bp,sp 首先棧頂棧底一樣 mov ax,[bp] 棧底的數據給ax add sp,2 棧頂指針移動 mov bp,sp 棧底位置和棧頂位置一樣
x86提供了指令,push 和pop,
push ax 把 ax壓棧,pop ax 出棧的值放到ax中
push的指令:push r16/m16/seg (可以是16位寄存器,2個字節的內存,或者段寄存器)
pop 一樣
注意:需要自己控制堆棧的平衡,
操作單位是字
5 標志寄存器傳送指令
作用:
add ax ,1 add ax,1 //這種情況標志寄存器的值還沒有保存
有兩對4條指令(分別對應8位寄存器,和16位寄存器)
低八位傳送
LAHF 和 SAHF
16位傳送
PUSHF 和 POPF
LAHF 代表 的意思 第一個字母 L代表load(加載的意思) AH八位寄存器AH,F是標志位
表示把 Flag標志寄存器里面的低八位標志,傳送到 AH中
LAHF ;AH←FLAGS的低字節 LAHF指令將標志寄存器的低字節送寄存器AH SF/ZF/AF/PF/CF狀態標志位分別送入AH的第7/6/4/2/0位,而AH的第5/3/1位任意
SAHF S可以理解為設置,或者保存的意思 ,就是 AH的高八位當做標志位給Flag寄存器的標志位賦值
表示我們通過AH的值,設置flag標志寄存器
SAHF ;FLAGS的低字節←AH SAHF將AH寄存器內容送FLAGS的低字節 用AH的第7/6/4/2/0位相應設置SF/ZF/AF/ PF/CF標志
標志位都清零
xor ah,ah (為什么用這個,因為這個CPU尋址的時候指令執行周期短,如果 寫成 mov ah,0那么帶有立即數所以比較慢) SAHF //清零標志位
PUSHF 和 POPF
pushf
的功能是將標志寄存器的值壓棧
SP←SP-2 ;SS:[SP]←FLAGS PUSHF指令將標志寄存器的內容壓入堆棧,同時棧頂指針SP減2
popf
是從棧中探出數據,輸入標志寄存器。
;FLAGS←SS:[SP] ;SP←SP+2 POPF指令將棧頂字單元內容送標志寄存器,同時棧頂指針SP加2
pushf 和 popf,為直接訪問寄存器提供了方法。
格式
pushf//這兩條指令后面都不加東西,默認的操作對象是:所有的標志寄存器。 popf
標志位都清零
pushf 獲取標志位到ax中,但是需要pop獲取 pop ax xor ax,ax 獲取到了設置為0 push ax 重新壓棧 popf 設置標志寄存器,一般來說不用設置標志寄存器的高八位
單獨修改標志寄存器某一位
pushf 保存全部標志到堆棧 pop ax 從堆棧中取出全部標志 or ax,0100h 設置D8=TF=1,這個地方就是對某一位設置 ax其他位不變 push ax 將ax壓入堆棧 popf FLAGS←AX//設置所有標志寄存器
6 地址傳送指令
lea 和mov 區別
lea簡單的說,lea指令可以用來將一個內存地址直接賦給目的操作數,例如:
lea eax,[ebx+8]就是將ebx+8這個值直接賦給eax,而不是把ebx+8處的內存地址里的數據賦給eax。
而mov指令則恰恰相反,例如:
mov eax,[ebx+8]則是把內存地址為ebx+8處的數據賦給eax。
LEA 有效地址傳送指令 例如 LEA AX,[bp] 這樣

LEA r16,mem (具體查詢 inter手冊) lea ax,[BX+SI+8]//精簡寫法,很快,兩個加法比一個lea慢
上面這樣寫只是求出內存地址,假設bp的值是2000,則給ax是2000,而不是2000里面的內容,這樣寫比add快,但是真正用法不是這樣的,真正用法就是求內存地址而已(注意不是求出內存單元的值,如果寫成 add ax,[bp],如果是這樣,那么ax的值就不是2000了,就是2000地址里面的內容了)
LDS LES 指針傳送指令 :程序一大,數據段就應該有很多,LDS和LES指令可以使用兩個段寄存器來回切換
LDS r16,mem ;r16←mem, ;DS←mem+2 LDS指令將主存中mem指定的字送至r16,並將mem的下一字送DS寄存器
LES r16,mem ;r16←mem, ;ES←mem+2 LES指令將主存中mem指定的字送至r16,並將mem的下一字送ES寄存器
例如:
切換段寄存器
mov word ptr [3060h],0100h mov word ptr [3062h],1450h les di,[3060h] //es=1450h,di=0100h lds si,[3060h] //ds=1450h,si=0100h
7 輸入輸出指令
匯編語言中,CPU對外設的操作通過專門的端口讀寫指令來完成;
讀端口用IN讀指令,寫端口用OUT寫指令。
在往鍵盤寫數據里的時候,需要更改標志位.才能out
IN AL,21H;表示從21H端口讀取一字節數據到AL IN AX,21H;表示從端口地址21H讀取1字節數據到AL,從端口地址22H讀取1字節到AH MOV DX,379H IN AL,DX ;從端口379H讀取1字節到AL OUT 21H,AL;將AL的值寫入21H端口 OUT 21H,AX;將AX的值寫入端口地址21H開始的連續兩個字節。(port[21H]=AL,port[22h]=AH) MOV DX,378H OUT DX,AX ;將AH和AL分別寫入端口379H和378H
算術運算類指令
加法指令
ADD reg,imm/reg/mem == reg←reg+imm/reg/mem ADD mem,imm/reg == mem←mem+imm/reg
ADC帶進位的加法:兩數結果加上標志位,這個指令做16位寄存器模擬32位加法運算
mov ax,4652h ;ax=4652h add ax,0f0f0h ;ax=3742h,CF=1 mov dx,0234h ;dx=0234h adc dx,0f0f0h ;dx=f325h,CF=0 //低位先做sdd運算,高位在做sdc運算 DX.AX=0234 4652H +F0F0 F0F0H ------------------ =F325 3742H
ADC reg,imm/reg/mem == reg←reg+imm/reg/mem+CF ADC mem,imm/reg == mem←mem+imm/reg+CF
增量INC,INC指令不影響進位CF標志,按定義設置其他狀態標志
INC reg/mem //很簡單,寄存器,或者內存自增1,C語言中相當於i++, ++i
例:
INC bx //bx自增1 INC byte ptr[bx] //地址自增
減法指令
SUB reg,imm/reg/mem == reg←reg-imm/reg/mem SUB mem,imm/reg == mem←mem-imm/reg
SBB帶借位的減法:十六位寄存器模擬三十二位寄存器減法
mov ax,4652h ;ax=4652h sub ax,f0f0h ;ax=5562h,CF=1 mov dx,0234h ;dx=0234h sbb dx,f0f0h ;dx=1143h,CF=1 //低位先做sub運算,高位在做sbb運算 ;DX.AX=0234 4652H -F0F0 F0F0H =1143 5562H
0000 = fff16 //這里0000不夠減,所以要向前借位,最后借到為fff16,cf=1 - - ffff ffff =0001 =0001
SBB reg,imm/reg/mem == reg←(reg-(imm/reg/mem)-CF) SBB mem,imm/reg == mem←mem-imm/reg-CF
自減
DEC,不能進行大數運算,因為沒有影響借位寄存器
DEC reg/mem == reg/mem←reg/mem-1
INC(自增)指令和DEC(自減)指令都是單操作數指令,
主要用於對計數器和地址指針的調整
NEG求補指令,影響cf進位標志位
NEG reg/mem == reg/mem←0-reg/mem
請注意,CPU並不會執行補碼,而是寫成
SUB 0,1 //用0減去操作數1,然后結果返回操作數
求補運算也可以表達成,將操作數按位取反后加1,
NEG指令對標志的影響與用零作減法的SUB指令一樣
CMP 比較指令,不影響操作數,只影響標志寄存器
1.CMP指令是將目的操作數減去源操作數,按照定義相應的設置狀態標志
2.CMP指令執行的功能與SUB指令(相減指令)一樣,但是不同的是CMP指令之根據結果設置標志位
而不修改值
機器碼是39代表的是CMP指令

CMP reg,imm/reg/mem CMP mem,imm/reg
例子:
cmp al,100 jz below //jz :al == 100則 zf==1 會跳轉到below執行,相當於c語言的goto指令 below: ...
乘法指令
MUL (無符號字節乘法)
注意:8位寄存器相乘要放到16位寄存器,16位寄存器相乘要放到32位寄存器,必須放到
al,ax
指令格式: ax = al * r8/m8 ax(16位寄存器)存放 al * r8(八位寄存器)或者 m8(內存中八位的值)
mov al,0b4h ;al=b4h=180 mov bl,11h ;bl=11h=17 mul bl ;ax=Obf4h=3060 ;OF=CF=1,AX高8位不為0
IMUL有符號的字節乘法
IMUL r8/m8 ax = al * r8/m8 和上面一樣,結果放到ax中,al可以×八位的寄存器,或者內存取出的數值的8位數值
mov al,b4h ;al=b4h=-76 mov bl,11h ;bl=11h=17 imul bl ;ax=faf4h=-1292 ;OF=CF=1,AX高8位含有效數字
除法指令
DIV
DIV r8/m8 ;無符號字節除法: AL←AX÷r8/m8的商,Ah←AX÷r8/m8的余數
mov ax,0400h ;ax=400h=1024 mov bl,0b4h ;bl=b4h=180 div bl ;商al=05h=5 ;余數ah=7ch=124
IDIV
IDIV r8/m8 ;有符號字節除法: AL←AX÷r8/m8的商,Ah←AX÷r8/m8的余數
mov ax,0400h ;ax=400h=1024 mov bl,0b4h ;bl=b4h=-76 idiv bl ;商al=f3h=-13 ;余數ah=24h=36
SHR 右移一定程度可以替代除法但是不能求余數 ,只能求2的倍數,
注意:有符號數不能右移,因為會丟失精度,計算機的除法是沒有小數位的,無符號除法則可以右移,不會影響結果
比如-3/2就錯了,用右移動就錯了
用法:
Usage: SHR dest,count //后面跟操作數和位移量
fd 1111 1101 -》 1111 1110 結果為-2了,因為丟失了精度
and ax,1 求除2的余數 ,如果結果為1則除2余1,如果結果為0則整除2,如果要判斷除4的余數,則
and ax,11 這樣就求出除4的余數了。
5除2 求余數 0101 & 1 -------- 1 //結果為1,則5除2有余數為1 9除4 求余數 1001 & 11 ---------- 1 //結果為1,則9除4有余數為1
shr 和 and ax ,1 配合,可以替代除法運算
符號擴展指令,不影響標志位
CBW 8位拓展為16為,符號位填充高位字節
CBW ;AL的符號擴展至AH ;如AL的最高有效位是0,則AH=00 ;AL的最高有效位為1,則AH=FFH。AL不變
例子:
mov al,80h ;al=80h cbw ;ax=ff80h mov al 7fh ;al =7fh cbw ;ax=007fh
CWD 16位拓展到32位,用dx來保存拓展位,符號位填充高位字節
CWD ;AX的符號擴展至DX ;如AX的最高有效位是0,則DX=00 ;AX的最高有效位為1,則DX=FFFFH。AX不變
十進制調整指令(不常用)
十進制數調整指令對二進制運算的結果進行十進制調整,以得到十進制的運算結果
分成壓縮BCD碼和非壓縮BCD碼調整
BCD壓縮碼就是通常的8421碼;它用4個二進制位表示一個十進制位,一個字節可以表示兩個十進制位,即00~99
36 表示十進制的三十六,不是十六進制的36
原理:如果al大於9就+6,不大於就不加6,
---------------------------------------------------------------------------------------------------------------------------
BCD非壓縮碼用8個二進制位表示一個十進制位,只用低4個二進制位表示一個十進制位0~9,高4位任意,通常默認為0
0306 表示十進制的36,不是十六進制的36
BCD壓縮碼的加法和減法
DAA:BCD壓縮嗎的加法
(ADD AL,i8/r8/m8)//可以add指令,也可以adc指令 (ADC AL,i8/r8/m8) DAA ;AL←將AL的加和調整為壓縮BCD碼
例子
39+1如果變為4a就是十六進制運算 使用DAA則結果為40,符合十進制運算結果
DAS:BCD壓縮嗎的減法
(SUB AL,i8/r8/m8)//可以sub指令,也可以sbb指令 (SBB AL,i8/r8/m8) DAS ;AL←將AL的減差調整為壓縮BCD碼
12 -3 如果變為0f就錯了,運算結果為16進制的結果 使用DAS則結果為9,符合十進制運算結果
注意:使用DAA或DAS指令前,應先執行以AL為目的操作數的加法或減法指令
BCD非壓縮碼的加法和減法
AAA和AAS指令在調整中產生了進位或借位,則AH要加上進位或減去借位,同時CF=AF(低4位進位檢測)=1,否則CF=AF=0;它們對其他標志無定義
AAA :BCD非壓縮碼的加法
(ADD AL,i8/r8/m8) (ADC AL,i8/r8/m8) AAA ;AL←將AL的加和調整為非壓縮BCD碼 ;AH←AH+調整的進位
例子:
mov ax,0608h ;ax=0608h,非壓縮BCD碼表示真值68 mov bl,09h ;bl=09h,非壓縮BCD碼表示真值9 add al,bl aaa ;十進制調整:ax=0707h,實現非壓縮BCD碼加法:68+9=77
AAS :BCD非壓縮碼的減法,注意:AAS只負責al,ah他不負責
(SUB AL,i8/r8/m8) (SBB AL,i8/r8/m8) AAS ;AL←將AL的減差調整為非壓縮BCD碼 ;AH←AH-調整的借位
例子:
mov ax,0608h ;ax=0608h,非壓縮BCD碼表示真值68 mov bl,09h ;bl=09h,非壓縮BCD碼表示真值9 sub al,bl aas ;十進制調整:ax=0509h, 實現非壓縮BCD碼減法:68-9=59
BCD非壓縮碼的乘法和除法:AAM和AAD指令根據結果設置SF、ZF和PF,但對OF、CF和AF無定義
AAM:BCD非壓縮乘法,AAM指令跟在字節乘MUL之后,將乘積調整為非壓縮BCD碼
(MUL r8/m8) AAM ;AX←將AX的乘積調整為非壓縮BCD碼
例子:
mov al,08h //ax=08h,非壓縮BCD碼表示真值68 mov bl,09h //bl=09h,非壓縮BCD碼表示真值9 mul bl aam 十進制調整:ax=0702h,實現非壓縮BCD碼乘法:8×9=72
AAD:BCD非壓縮除法,AAD指令跟在字節除DIV之前,先將非壓縮BCD碼的被除數調整為二進制數
(DIV r8/m8) AAD ;AX←將AX中非壓縮BCD碼擴展成二進制數
例子:
mov ax,0608h //ax=0608h,非壓縮BCD碼表示真值68 mov bl,09h //bl=09h,非壓縮BCD碼表示真值9 aad div bl ;除法運算:商al=07h,余數ah=05h,實現非壓縮BCD碼除法:68÷9=7(余5)
位操作指令
AND:
格式: AND OPRD1,OPRD2
功能: 對兩個操作數實現按位邏輯與運算,結果送至目的操作數.本指令可以進行字節或字的‘與’運算,
OPRD1<--OPRD1 and OPRD2.
AND reg,imm/reg/mem AND mem,imm/reg
作用:
1 判斷一個數某位是0還是1
1001 & 1000 //判斷最高位是否為1 ------------ 1000 //得到最高位為1
2 給數字的某一位置為0
1111 & 1000 ------ 1000 //后三位被置為了0
注意:AND指令設置CF = OF = 0,根據結果設置SF、ZF和PF狀態,而對AF未定義
and ax,not 1(1取反)
邏輯或運算
OR
作用:置數字的某位數為1
OR reg,imm/reg/mem OR mem,imm/reg
注意:OR指令設置CF = OF = 0,根據結果設置SF、ZF和PF狀態,而對AF未定義
邏輯異或指令
XOR
作用:對某個數子的某些位數取反
例子:最高位4位取反
1010 1010 xor 1111 0000 -------------- 0101 1010
注意:XOR指令設置CF = OF = 0,根據結果設置SF、ZF和PF狀態,而對AF未定義
邏輯非指令
NOT
NOT reg/mem
注意:NOT指令是一個單操作數指令,NOT指令不影響標志位
測試指令
TEST
作用:Test命令將兩個操作數進行邏輯與運算,並根據運算結果設置相關的標志位。但是,Test命令的兩個操作數不會被改變。運算結果在設置過相關標記位后會被丟棄
TEST reg,imm/reg/mem TEST mem,imm/reg
注意:AND指令設置CF = OF = 0,根據結果設置SF、ZF和PF狀態,而對AF未定義
例子:
test al,01h ;測試AL的最低位D0 jnz there ;標志ZF=0,即D0=1 ;則程序轉移到there ... ;否則ZF=1,即D0=0,順序執行 there: ...
移位指令
SHL reg/mem,1/CL //邏輯左移 SHR reg/mem,1/CL //邏輯右移 SAL reg/mem,1/CL //算數左移 SAR reg/mem,1/CL //算數右移
移位指令的第一個操作數是指定的被移位的操作數,
可以是寄存器或存儲單元,后一個操作數表示移位位數,該操作數為1,表示移動一位;當移位位數大於1時,則用CL寄存器值表示,該操作數表達為CL

移位指令對標志的影響
按照移入的位設置進位標志
CF
根據移位后的結果影響
SF、ZF、PF
對AF沒有定義
如果進行一位移動,則按照操作數的最高符號位是否改變,相應設置溢出標志OF:
如果移位前的操作數最高位與移位后操作數的最高位不同(有變化),則OF = 1;否則OF = 0。當移位次數大於1時,OF不確定
----------------------------------------------------------------------------------------------------------------------------
邏輯左移
shl :各二進制位全部左移若干位,高位丟棄,低位補0
每移動一次寫一行代碼是賺的,連續唯一是效率低的 注意最高位去cl位了,沒有丟棄,最高位會一直覆蓋最高位 shl 取代乘2的乘法
邏輯右移
shr :各二進位全部右移若干位,低位丟棄,高位補0或者補符號位
每移動一次寫一行代碼是賺的,高位補0 shr 取代除2的除法,注意是整除的情況下才可以
算數左移
sal
sal和shl 一樣的,反匯編不會翻譯sal,debug沒有sal 指令
算數右移 :
sar
注意:高位補符號位
循環移位:
ROL reg/mem,1/CL ;不帶進位循環左移 ROR reg/mem,1/CL ;不帶進位循環右移 RCL reg/mem,1/CL ;帶進位循環左移 ,進位保存在cf,下次循環+cf的進位值 RCR reg/mem,1/CL ;帶進位循環右移 , 進位保存在cf,下次循環+cf的進位值
作用:
高4位和低4位互換,應用在加密算法 比如一個8位的數,判斷有多少個1,這個數字移動8次就能數出有多少個1,並且不改變源數
帶進位循環示意圖

循環移位指令對標志的影響
按照指令功能設置進位標志CF
不影響SF、ZF、PF、AF
如果進行一位移動,則按照操作數的最高符號位是否改變,相應設置溢出標志OF:
如果移位前的操作數最高位與移位后操作數的最高位不同(有變化),則OF = 1;否則OF = 0。當移位次數大於1時,OF不確定
串操作指令
串操作指令是8086指令系統中比較獨特的一類指令,采用比較特殊的數據串尋址方式,
在操作主存連續區域的數據時,特別好用、因而常用
重點掌握: MOVS STOS LODS CMPS SCAS REP 一般了解: REPZ/REPE REPNZ/REPNE
串尋址方式
源操作數用寄存器SI尋址,默認在數據段DS中,但允許段超越:DS:[SI] 目的操作數用寄存器DI尋址,默認在附加段ES中,不允許段超越:ES:[DI] 每執行一次串操作指令,SI和DI將自動修改: ±1(對於字節串)或±2(對於字串) 執行指令CLD指令后,DF = 0,地址指針增1或2 執行指令STD指令后,DF = 1,地址指針減1或2
MOVS串傳送 memcpy
作用:把字節或字操作數從主存的源地址傳送至目的地址
MOVSB
MOVSB ;字節串傳送:ES:[DI]←DS:[SI] //段寄存器ds:si的位置傳送到段寄存器es:di的位置 ;SI←SI±1,DI←DI±1 //si di自動加1
例子:
mov si,offset source //源偏移地址 mov di,offset destination//目的偏移地址 movsb //傳送一個字節
MOVSW
MOVSW ;字串傳送:ES:[DI]←DS:[SI] ;SI←SI±2,DI←DI±2 //si di自動加2

MOVSB:傳送一個字節,之后SI和DI(或者ESI和EDI)加/減1
MOVSW:傳送一個字 =2字節,之后SI和DI(或者ESI和EDI)加/減2
MOVSD:傳送一個雙字 =4字節,之后SI和DI(或者ESI和EDI)加/減4
STOS串存儲 memset
作用:把AL或AX數據傳送至目的地址
STOSB ;字節串存儲:ES:[DI]←AL ;DI←DI±1
STOSW ;字串存儲:ES:[DI]←AX ;DI←DI±2
例子:
CLD //置標志為DF=0 MOV AL,3 //賦值al寄存器為3 LEA DI,[EA] //賦值目的地址指針 STOSW //執行指令使al中的內容拷貝到di目的地址

LODS串讀取
相當於memchr :在內存中搜索二進制數據
作用:把指定主存單元的數據傳送給AL或AX
LODSB ;字節串讀取:AL←DS:[SI] ;SI←SI±1
LODSW ;字串讀取:AX←DS:[SI] ;SI←SI±2
例子:
CLD //置標志為DF=0 MOV SI,[EA] //初始si指針的偏移位置 LODSW //執行指令賦值一個子數據到AX
CMPS串比較
將主存中的源操作數減去至目的操作數,以便設置標志,進而比較兩操作數之間的關系
簡而言之:
意思就是 源內存中的數(可以理解為數,也可能是字符串的ASCII碼) 減去 目的內存中的數,根據結果設置標志位
比如 源內存 的數字是 1 目的內存中 也是1 那么 1 -1 就為0,0是結果,根據結果設置一下標志位 則ZF = 1,也就是源和目的相等,相當於
memcmp
CMPSB ;字節串比較:DS:[SI]-ES:[DI] ,SI←SI±1,DI←DI±1
CMPSW ;字串比較:DS:[SI]-ES:[DI],SI←SI±2,DI←DI±2
SCAS串掃描
將AL/AX減去至目的操作數,以便設置標志,進而比較AL/AX與操作數之間的關系
簡而言之:
就是你要搜索的字節,放到AL,或者AX中,然后會和DI去比較,然后根據結果設置標志,在C語言中,這個相當於
memchr命令:
從buff所指內存區域的前count個字節查找字符ch。 void *memchr( const void *buf, int c, size_t count );
SCASB ;字節串掃描:AL-ES:[DI] ,DI←DI±1
SCASW ;字串掃描:AX-ES:[DI], DI←DI±2
REPEAT重復前綴指令
簡單理解為就是為串操作單獨提供的循環指令,比如我們上面要用MOVS串操作指令的時候,把源寄存器中的值,拷貝到目的寄存器中,假設我們有個HELLO 我們要使用五次 MOVSB命令才能拷貝過去
現在提供了一個為串操作的循環
重復前綴分為兩類,3條指令
1.配合使用,
MOVS,STOS,LODS 的時候,使用指令REP前綴,不影響標志
2.配合使用
CMPS,SCAS,指令,使用REPZ和REPNZ前綴
然后重復次數放到cx寄存器中
mov cx,3 rep movsb
REP前綴可以理解為:當數據串沒有結束(CX≠0),則繼續傳送
REPZ,和REPNZ解析
REPZ: 1.每次執行串指令,則CX-1 2.判斷零標志位(ZF)是否為零 3.如果CX == 0,或者 ZF == 0 則重復執行結束 注意可以簡單理解為,cx !=0 && zf == 1 的時候繼續循環 ----------------------------------------------------- REPNZ: 1.每次執行串指令,則CX-1 2.判斷零標志位(ZF)是否為1 3.如果CX == 0,或者 ZF ==1 則重復執行結束 REPNZ/REPNE的前綴,可以簡單理解為 cx != 0 && zf ==0 的時候繼續.
機器代碼
F3,表示指令重復執行
注意:帶循環的指令用
-T 進去看
repz,默認z可以不寫:重復執行命令
補充:
ptr 指令相當於c語言的強轉
mov ax,word ptr [bx]; 是把內存地址等於“BX寄存器的值”的地方所存放的數據,賦予ax。由於只是給出一個內存地址,不知道希望賦予ax的,是byte還是word,所以可以用word明確指出;如果不用,既(mov ax, [bx]; )則在8086中是默認傳遞一個字,既兩個字節給ax
or 是或運算,A OR B的結果:當A、B中只要有一個或者兩個都為1時,結果為1,否則為0;
xor 是異或運算,A XOR B的結果:當A、B兩個不同時結果為1,否則為0。
鍵盤兩個寄存器:1 一個存按了什么 2 一個存標志位
-r ip 修改下一條指令
int 21 是指令執行功能調用,相當於已經封裝好的類
》0《0??標志位判斷
ffff -1為-2的補碼
1000 0010 //-2的源碼 1111 1101 //取反 1111 1110 //取反加1 =FE
一個int最大為 42億
對標志沒有定義:指令執行后這些標志是任意的、不可預測(就是誰也不知道是0還是1)
對標志沒有影響:指令執行不改變標志狀態
ax
,0fffh 加0代表十六進制
公交和廣告牌,空調都用bcd碼,常用在單片機上
NUM 1 dw 2,
dup(2) 作用為定義兩個dw類型的2
c語言位移根據類型判斷
--------------------------------------------------------------------------------------------------------------
1 、OFFSET是將數值回送變量或標號的
偏移地址值. ,一般用於全局變量
2. LEA是將數值回送變量或標號的有效地址值.