匯編第三日
在.asm文件中寫mov al, [0],對於編譯器來說只是將0賦值給al(不過寫[0]相當於寫ds:[0],寫[1],[2]....這些就不相同了)
為了表示我們想要的ds:[0]:
1.改寫成mov al, ds:[0]
2.
mov bx, 0
mov al, [bx]
所以bx寄存器基本上與內存地址掛鉤
cx寄存器基本上記錄loop循環次數,也可記錄源代碼行數
loop基本語法:
mov cx, 11
標號:循環體
loop 標號 ;這三條語句盡量靠近,防止其他語句對寄存器值進行修改
loop執行過程:
(cx) = (cx) - 1 //
若(cx)不為0,跳轉到標號執行;若為0,執行loop下一條語句
編寫匯編代碼時,若想表示16進制數據,在數據後加上‘H‘ 或 ‘h’,並且數據不能以字母開頭,例如FFFFH只能寫成0FFFFH.
add ax, ax :表示冪的計算
add ax, data :表示乘法的計算
對於8位數據與16位寄存器數據相加,結果放在寄存器中:
首先8位數據無法直接使用 add 來與16位數據相加,所以8位數據先放到充當中介作用的寄存器的低8位,高8位置0,之後和16位寄存器相加即可
實現局部代碼:
mov bx, 0 movcx, 12 s: mov al, [bx] mov ah, 0 add dx, ax inc dx loop s
inc:(bx) = (bx) + 2
;封號作為註釋
段前綴概念:
mov ax,cs:[0]/ds:[0](ds和cs即為段前綴)
一般PC中,0:200 --- 0:2FF為安全空間即不幹擾OS運行
可以情況下,ds:[...]化一下更為簡單,例如 200:100 - 200:1FF 可以化成 210:0 - 210:FF等等
dw指令和db指令:
dw:define word 定義字型數據
db:define byte 定義字節數據
dw語法:
dw 0102H,0304H,0506H
0102H占了一個字(兩個內存存儲空間)
一旦出現dw和或db,那麽定義標號就很有必要。之前沒有定義dw或db時,沒有定義標號是不影響程序執行和結果,雖然報個warning:沒有程序入口地址;但是定義了dw或db時,若沒有標號,那麽當匯編指令轉化成機器指令時,CPU會認為用戶定義的數據也為指令,從而執行出錯。所以要註明標號指明程序入口地址。
但是有個特殊點:當我們把指令寫為第一個段,db或dw定義在其後的話,CPU還是從第一段指令開始執行,直到end結束執行,結果依然正確
匯編指令結尾end作用:
1.通知編譯器程序結束
2.得到程序入口地址(真正執行機器指令時,CPU會先去找end,從而根據其後的標號找到程序入口地址)
若數據或指令需要大於64KB(8086:一個段最大容量)時,需要多個段空間來執行,主要是封裝的思想,畢竟64KB比較大,而之後的i386的32位對應最大段容量為4GB
實例:
assume cs:code,ds:data,ss:stack //將地址與相應的寄存器掛鉤 data segment dw 0123h,0456h data ends stack segment dw 0,0 stack ends code segment start: mov ax,stack mov ss,ax //也無法給ss mov sp,16 mov ax,data //同理標號data為數據無法直接給ds mov ds,ax push ds:[0] push ds:[2] pop ds:[2] pop ds:[0] mov ax,4c00h int 21h code ends end start
ES為附加段寄存器
當可執行文件加載進內存時,CS:IP會被設置成end 標號對應的程序入口地址,從而開始執行第一條指令
CPU靠CS:IP,SS:SP,DS:[...]來認識代碼段,棧,數據段
Done!!!
匯編第三日