1. 程式人生 > >匯編第三日

匯編第三日

col ron 文件加載 color 相加 匯編 基本語法 編譯器 使用

在.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
    mov
cx, 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!!!                 

匯編第三日