匯編指令:機器碼的助記符辛臊,有對應(yīng)的機器碼
偽指令:沒有對應(yīng)的機器碼,由編譯器執(zhí)行房交,計算機并不執(zhí)行
其它符號:+-*/等由編譯器識別彻舰,沒有對應(yīng)的機器碼
每一種CPU都有自己的匯編指令集
CPU可以直接使用的信息在存儲器中存放
在存儲器中指令和數(shù)據(jù)沒有任何區(qū)別,都是二進制信息
存儲單元從零開始順序編號
一個存儲單元可以存儲8個bit候味,即8位二進制數(shù)
計算機最小信息單位是bit刃唤,1bit= 1個二進制位,8bit = 1Byte(字節(jié))
1KB = 1024B白群,1MB = 1024KB尚胞,1GB = 1024MB,1TB = 1024GB
地址總線的寬度決定了CPU的尋址能力
數(shù)據(jù)總線的寬度決定了CPU與其它器件間一次數(shù)據(jù)傳送量
控制總線的寬度決定了CPU對其它器件的控制能力
數(shù)據(jù)總線
一個CPU有多少根數(shù)據(jù)總線帜慢,就可以說它是多少位的CPU笼裳,
比如32位CPU有32根數(shù)據(jù)總線
每根總線每次可以傳遞1個bit
所以32位的CPU一次最多可以傳送4個字節(jié)的數(shù)據(jù)量
1比特 = 1個二進制位
1字節(jié) = 8比特 (1Byte = 8bit)
1KB = 1024Byte,1MB = 1024KB粱玲,1GB = 1024MB躬柬,1TB = 1024GB
1Byte = 8bit,1Btye等于8個二進制位抽减,那么可以表示的最大數(shù)據(jù)為1111 1111允青,
也就是十進制的255,也等于16進制的0xFF卵沉。
所以得到:2個十六進制數(shù)表示1個字節(jié)颠锉,1個16進制位表示4bit
數(shù)據(jù)寄存器 指針和變址寄存器 段寄存器 控制寄存器
AX:AH, AL SP 堆棧指針 CS 代碼段 IP 指令指針
BX:BH, BL BP 基數(shù)指針 DS 數(shù)據(jù)段 FLAG 狀態(tài)標志
CX:CH, CL SI 源變址 SS 堆棧段
DX:DH, DL DI 目的變址 ES 附加段
8086CPU地址總線20根,數(shù)據(jù)總線16根偎箫,16根數(shù)據(jù)總線最大可以描述0xFFFF木柬,也就是16位64KB的數(shù)據(jù),
所以最多可以尋址64KB的內(nèi)存地址淹办,然而20根地址總線支持1M的尋址范圍眉枕,為了解決該問題,8086CPU
的解決辦法是: 物理地址 = 段地址 * 16 + 偏移地址
例子: CS:IP
0xCFFA7 = 0xCFFA * 16 + 0x0007 0xCFFA:0x0007
0xCFFA7 = 0xCFF0 * 16 + 0x00A7 0xCFF0:0x00A7
0xCFFA7 = 0xCF00 * 16 + 0x0FA7 0xCF00:0x0FA7
0xCFFA7 = 0xC000 * 16 + 0xFFA7 0xC000:0xFFA7
8086CPU不支持直接對段地址和指針賦值,若想修改CS:IP的值速挑,
可以使用 jmp 段地址:偏移地址 來實現(xiàn)谤牡,其作用為:
jmp.段地址修改CS
jmp.偏移地址修改IP
當我們僅需要修改IP的值,此時的jmp一個合法的寄存器即可姥宝,比如修改IP的值為3H:
mov ax,3h
jmp ax
cs = 1000h
ip = 4h
mov ax,2ecH
jmp ax
此時 cs = 1000h,ip = 2ecH
jmp不允許直接賦值翅萤,必須要先把值賦給寄存器之后,再jmp這個寄存器腊满,
此限制同樣適用于call等指令
SS:SP
堆棧段:棧頂指針
8086CPU是16位的套么,所以SP也是16位的,其可以表示的最大數(shù)據(jù)為0xFFFF 也就是64KB
PUSH 入棧 PUSH AX ;將AX的數(shù)據(jù)壓如棧
POP 出棧 POP AX ;將棧頂指針指向的數(shù)據(jù)送入AX
棧是以字為單位的碳蛋,也就是2個字節(jié):
PUSH AX 會使得SP-=2胚泌,因為棧底是高位,棧頂是低位肃弟,所以壓棧操作會使棧頂指針向上(低位)移動
而AX是16位寄存器玷室,也就是2個字節(jié),所以SP會減2
需要注意的是笤受,對于16位CPU穷缤,PUSH操作即壓棧2個字節(jié)的數(shù)據(jù),所以即使PUSH AH/AL箩兽,也是2個字節(jié)
POS AX 則使得SP+=2津肛,它與PUSH指令的操作正好相反
Loop指令和cx寄存器配合使用,語法:
mov cx,循環(huán)次數(shù)
標號:
循環(huán)體
loop 標號
執(zhí)行流程:
1.先將cx寄存器自減 cx = cx - 1
2.判斷cx的值
如果不為0則執(zhí)行標號的代碼汗贫,再次執(zhí)行步驟1
如果為0則執(zhí)行l(wèi)oop后的代碼快耿,跳出循環(huán)
示例:計算2^6
mov ax,2H
mov cx,5 ;和do while一樣,標號bh會先執(zhí)行一次芳绩,再進入循環(huán),所以這里是5
bh: add ax,ax
loop bh
在我們計算內(nèi)存數(shù)據(jù)時撞反,需要注意溢出問題妥色,例子:
取FFFF0H - FFFF2H所有值得和存到DX寄存器中,數(shù)據(jù)如下:
FFFF0H --- FFH
FFFF1H --- FFH
FFFF2H --- FFH
此問題有2點需要特別注意
1.一個內(nèi)存地址就是1個字節(jié)遏片,即8bit嘹害,所以最大值只能存儲FFH,1AC吮便、30EB這些肯定存不了
2.當我們使用16位寄存器比如AX對FFFF0H取值時笔呀,
因為AX是2個字節(jié),所以會讀取FFFF0H和FFFF1H的值髓需,這顯然與我們的預期違背许师,所以
此時我們需要使用8位寄存器來取值以保證只讀取一個內(nèi)存地址中的數(shù)據(jù),但是使用8位寄存器
又會出現(xiàn)溢出的問題,因為8位寄存器比如AL在運算FF+FF時并不會進位到AH微渠,而AL8位最多可以
表示FFH搭幻,所以溢出。解決方法為使用其它寄存器來過渡一下逞盆,如:
mov ax,ffffh
mov ds,ax
mov dx,0h
mov al,ds:[0] ;第一次獲取不存在溢出問題
mov ah,0h
add dx,ax
mov al,ds:[1] ;第二次獲取存在溢出問題
mov ah,0
add dx,ax ;因為這里使用dx和ax計算相加檀蹋,所以可以進位,就解決了溢出問題
mov al,ds:[2] ;第三次獲取存在溢出問題
mov ah,0
add dx,ax ;因為這里使用dx和ax計算相加云芦,所以可以進位俯逾,就解決了溢出問題
這樣,我們就利用16位寄存器可以進位的特點解決了8位寄存器溢出問題
偽指令
db(define byte) ;自定義字節(jié)
dw(define word) ;自定義字
db 20 dup(0) ;開辟20個字節(jié)的地址空間并用0填充
db 20 dup(5) ;開辟20個字節(jié)的地址空間并用5填充
saaume cs:code ;指定段地址
code segment ;定義段
...
cbegin:
...
...
;退出代碼
mov ah,4ch
int 21h
code ends ;結(jié)束段定義
end ;指示編譯器程序編碼結(jié)束舅逸,end后可增加表示指定程序的代碼段入口地址
比如end cbegin,此時begin標識之前的數(shù)據(jù)不會再被CPU當做代碼執(zhí)行