0x01 內存中的字存儲
CPU中,用16為寄存器來存儲一個字節(jié)髓介。同時又分為低八位和高八位惕鼓,由于內存單元是字節(jié)單元(一個單元存放一個字節(jié)),則一個字需要用兩個連續(xù)的內存單元來存放
字單元唐础,即存放一個字型數(shù)據(jù)(16位)的內存單元箱歧,有兩個地址連續(xù)的內存單元組成。
0x02 DS和[adress]
CPU要讀寫一個內存單元的時候一膨,必須先給出這個內存單元的地址呀邢。
DS寄存器,通常用來存放要訪問數(shù)據(jù)的段地址
實例:
mov bx,1000H
mov ds,bx
mov al,[0]
解釋:
- 8086CPU不支持直接將段地址送入段寄存器
- 可以用一個數(shù)據(jù)or指令寄存器 轉入到段寄存器 如上操作
- 最后一步是指 將1000:0 指向的地址內容存入 al中
0x03 字的傳送
因為8086CPU是16位結構豹绪,有16根數(shù)據(jù)線价淌,所以,可以一次性傳送16位的數(shù)據(jù)瞒津,也就是說可以一次性傳送一個字蝉衣。只要在MOV指令中給出16位的寄存器就可以進行16位數(shù)據(jù)的傳送了。
例
0x04 mov,add,sub指令
現(xiàn)已知mov指令有以下幾種形式
指令模式 | 例子 |
---|---|
mov 寄存器巷蚪,數(shù)據(jù) | mov ax,8 |
mov 寄存器买乃,寄存器 | mov ax,bx |
mov 寄存器,內存單元 | mov ax,[0] |
mov 內存單元钓辆,寄存器 | mov [0],ax |
mov 段寄存器,寄存器 | mov ds,ax |
add,sub 都和mov一樣都有相同的模式,可以自行在Debug中測試
0x05 數(shù)據(jù)段
定義:同段地址相同前联,我們可以采用地址連續(xù)功戚,起始地址為16的倍數(shù)的內存空間當作專門存儲數(shù)據(jù)的空間
例
123B0H~123B9H這一段地址專門用來存儲數(shù)據(jù) 可以成為數(shù)據(jù)段
訪問數(shù)據(jù)段的方式就是前面講解的DS用法
0x06 小結(一)
- 字在內存中存儲時,要用兩個地址連續(xù)的內存單元來存放似嗤,字的地位字節(jié)存放在低地址中啸臀,高位字節(jié)存放在高地址單元中。
- 用mov指令訪問內存單元烁落,可以在MOV指令中只給出單元的偏移地址乘粒,此時的段地址默認從DS寄存器中獲取
- [address] 表示一個偏移地址為address的內存單元
- 在內存和寄存器之間傳送字型數(shù)據(jù)時,高地址單元和高八位寄存器伤塌,低地址單元和低8位寄存器相對應
- mov,add,sub 都是具有同時操作兩個對象的指令灯萍,JMP只能操作一個
0x07 棧
棧:始終具有特殊的訪問方式的存儲空間,它的特殊性在于每聪,最后進入的空間的數(shù)據(jù)旦棉,最先出去。
簡議:先進后出药薯。
棧頂?shù)脑乜偸亲詈笕霔0舐澹鰲r,最先從棧中取出童本。棧的這種操作規(guī)則被稱為:LIFO(last in first out)后進先出
0x08 CPU提供的棧機制
8086CPU提供最基本的入棧和出棧指令真屯,PUSH和PHP
例
mov ax,0123H
push ax
mov bx,2266H
push bx
mov cx,1122H
push cx
pop ax
pop bx
pop cx
SS段寄存器和SP寄存器:
- 為了區(qū)分普通內存單元和棧內存單元CPU提供了類似CS:IP的工具SS:SP
- 任意時刻,SS:SP指向地址棧頂元素
- push和pop都是從SS:SP中獲取地址的
下圖接是8086CPU入棧操作
- 第一步 SS:SP 先移動
- 第二部 AX元素入棧
當初始化棧的時候SS:SP指向的地址為空的時候SS:SP會從下一個單元開始計算椙钣椋空間
下圖時POP出棧指令過程
- 跟入棧步驟相反绑蔫,先將數(shù)據(jù)傳送到寄存器中
- 再SP=SP+2 偏移地址轉移
注雖然SP指向的位置已經(jīng)變化但前面的數(shù)據(jù)還是沒有變化,當有新的PUSH進入時會覆蓋并寫入新數(shù)據(jù)
0x09 棧頂超界問題
下面兩圖是描述 PUSH滿棧和POP鄙煤,棧頂超出椓澜常空間的情況
滿棧進棧和空棧出棧都是棧頂越界問題
棧頂越界是很危險的,因為我們既然講一段空間安排為棧那么我們會把椞莞眨空間外的空間里放棄他用途的數(shù)據(jù)凉馆,這些數(shù)據(jù)可能時我們自己程序中的也可能是別的程序中的。但是由于我們入棧和出棧時的不小心亡资,而將這些數(shù)據(jù)澜共,代碼意外的改寫,將會引發(fā)一連串的錯誤锥腻。
我們再編程的時候要自己操心棧頂越界的問題嗦董,要根據(jù)可能用到的最大棧空間瘦黑,來安排棧的大小京革,防止入棧的數(shù)據(jù)太多而導致的越界奇唤;執(zhí)行出棧操作的時候也要注意,以防椘ヒ。空的時候繼續(xù)出棧導致的越界
0x10 push,pop 指令
指令格式 | 例子 |
---|---|
push 寄存器 | push ax |
push 段寄存器 | push [0] |
push 內存單元 (注意:棧操作都是以字為單位) | push 1122H |
POP相同
棧的綜述
- 8086CPU提供了棧的操作機制咬扇,在SS,SP中存放棧頂?shù)亩蔚刂泛推频刂?/li>
- push指令執(zhí)行步驟
- SP=SP-2
- 向SS:SP指向的子單元中送入數(shù)據(jù)
- pop指令執(zhí)行步驟
- 從SS:SP指向的字單元中讀取數(shù)據(jù)
- SP=SP+2
- 任意時刻SS:SP指向棧頂元素
- 8086CPU只記錄棧頂廊勃,椥负兀空間的大小要我們自己去管理
- 用棧來暫存數(shù)據(jù)以后要記得 LIFO 后進先出
- POP,PUSH實質上是一種內存?zhèn)魉椭噶钇碌妫⒁馑麄兊撵`活應用
0x11 棧段
棧段梭灿,地址段,數(shù)據(jù)段都相似不重復了冰悠。
棧段堡妒,代碼段,數(shù)據(jù)段
CPU按照我們的安排來訪問這些段屿脐,
- 數(shù)據(jù)段:將它的段地址放在DS中涕蚤,用mov,add,sub等訪問內存單元的指令時,CPU就將我們定義的數(shù)據(jù)段中的內容當做數(shù)據(jù)來訪問的诵。
- 代碼段:將它的段地址放在CS中万栅,將棧頂單元的偏移地址放在IP中,這樣CPU就執(zhí)行我們定義的代碼段中的指令
- 棧段:段地址在SS中西疤,將棧頂單元的偏移地址放在SP中烦粒,這樣CPU在需要進行棧操作的時候,比如執(zhí)行push,pop指令等代赁,就將我們定義的棧段當做椚潘空間來用