日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

汇编学习笔记(4)-伪指令(MASM)

發(fā)布時間:2024/1/17 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 汇编学习笔记(4)-伪指令(MASM) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言

  編寫匯編代碼的時候會使用到兩種語句,一種就是前面介紹的匯編指令又CPU提供功能支持,另一種呢叫做偽指令,偽指令是由匯編的編譯器提供支持。所以偽指令的運行結(jié)果都必須實在編譯的時候就能確定的,下面介紹的就是偽指令了。

  注意接下來介紹的偽指令都是基于MASM匯編編譯器,比較常用的還有NASM 它的語法以后有機會介紹

?

數(shù)值表達式

  數(shù)值表達式不是匯編指令,表達式的值是在匯編代碼的匯編過程中就由匯編編譯器計算出結(jié)果而寫到二進制程序中了,并不是在程序運行的過程中才計算的

  (1) 常數(shù)表達式

    常數(shù)就是直接的數(shù)字,直接寫數(shù)字默認表示10進制數(shù),也可以用符號指定為其他進制

    D = 十進制   ; MOV AL, 1234D

    B = 二進制   ; MOV AL,? 0101B

    H = 十六進制  ; MOV AL,? 0FFFFH , 注意常數(shù)必須是數(shù)字開頭不能是字母開頭,如果16進制數(shù)第一個數(shù)字是字母的話就要補一個0在前面

    Q = 八進制   ; MOV AL, 123Q

?

    因為在程序中字母也是數(shù)字,所以其實也可以直接將字母或者字符串當成數(shù)字,比如

    MOV AL, 'a'

    MOV AX,"ab"  ; 雙引號和單引號都是可以使用的

?

?  (2) 算數(shù)運算符

    就是簡單的 正(+) 負(-) 加(+) 減(-) 乘(*) 除(/) 模(mod)

    mov ax, 100+200

    mov ax, 100/2

?

  (3) 關系運算符

    等于(EQ) 不等(NE) 大于(GT) 小于(LT) 大于等于(GE) 小于等于(LE)

    如果等式成立則實際的值為0FFFF就是補碼表示的-1, 如果關系不成立那么結(jié)果就是0

    mov ax, 123 gt 234

    mov ax, 1234+5 lt 1235

?

  (4) 邏輯運算?

    與(and) 或(or) 非(not) 異或(xor) 左位移(shl) 右位移(shr)

    mov ax, 1 shl 3

    mov al, 3 and 47

?

  (5) 其他操作符

    HIGH LOW WIDTH MASK?

    HIGH 表示取數(shù)據(jù)的高八位

    LOW 表示取數(shù)據(jù)的低八位

??

地址表達式

  地址表達式所表示的是存儲器操作數(shù)的地址。前面介紹的各種尋址方式實際上也是地址表達式。

  一般格式是

  mov ax, varw+4

?

  注意 varw 變量或者標號的地址,這個是在編譯的時候就知道的,所以varw+4 計算出來的就是varw 地址偏移4的地址,所以AX的值不是 varw+4的值,而是varw+4 內(nèi)存地址處的值,所以AX的值是不確定的。

  當然還有其他的寫法

  [varw+bx]

  varw[bx]

  varw[bx+di]

  varw[bx][di]

?

變量和標號

  (1) 數(shù)據(jù)定義語句

    [變量名]? 變量類型 表達式[, 表達式]

    其中變量類型有

    DB  字節(jié)

    DW  字

    DD?  雙字

    

    所以數(shù)據(jù)定義就可以是這樣的

    a db 1,2,3,4,5

    db 7,8,9,10

    b dw 123,123,123

    c dd 123,?,?,?

?

    匯編中的數(shù)據(jù)定義意義其實就是C中的數(shù)組指針。這些數(shù)據(jù)都是順序存放在內(nèi)存中的,所以雖然第二行的數(shù)據(jù)沒有定義名字,但是因為他緊跟在a 數(shù)組之后 b數(shù)組之前,所以使用a+5,或者 b-1 也是可以訪問的,只是需要注意的是數(shù)據(jù)類型和 大端小端的問題。

    后面跟實際數(shù)據(jù)的就表示定義的時候就直接初始化了數(shù)據(jù),如果只是想留著位置,并不需要初始化的話也可以使用? 表示,?的意思就是只留位置不初始化內(nèi)容

  

    前面也說過,字符其實也可以表示為數(shù)字,所以也之后直接定義字符數(shù)組,下面的兩種方式都是可行的

    str? db “hello”

    str db "h","e","l","l","0"

  

  (2) 循環(huán)定義 DUP

    數(shù)字表達式 DUP(數(shù)據(jù)[, 數(shù)據(jù),數(shù)據(jù)...])

    有時候定義數(shù)組只是想預留一些空間,可能需要預留100個字節(jié)那么使用

    buff db ?,?,?,?.......??

    這種方式要打100個? 這樣顯然很沒效率所以有個偽指令可以幫忙

    buff db 100 dup(?);   定義100個DB 數(shù)據(jù)不用初始化

    也可以這樣

    buff? db 5 dup("ab") =?buff db 'a','b','a','b','a','b','a','b','a','b'

    dup 也是可以嵌套的比如

    buff db 2 dup(1,2,5 dup(?)) =? buff db 1,2,?,?,?,?,?,1,2,?,?,?,?,?

?

  (3)?this?  

     this 類型

     類型可以是byte word dword this返回下一個將分配的地址的

    my_byte equ this byte  ; equ是等效定義符號,下面或解釋

    my_word dw 8 dup(?)

    這樣就是定義了一個 byte的地址指針指向了一個 word數(shù)組等效的C語言就是

    short[8]? my_word[];

    byte* my_byte = (byte*)my_word;

?

  (4) 等價語句? EQU

    符號名 EQU 表達式

    說白了 EQU 就類似C的 #define 語句?

    用法可以是這樣的

    COUNT EQU 100      ; #define COUNT 100

    BUFF_EN EQU 4*COUNT  ;?#define?BUFF_EN? 4*COUNT

    HELLO EQU "how are you" ? ;?#define HELLO "how are you"

    MOVE EQU MOV     ? ?;#define MOVE MOV

?   

    VARW EQU THIS WORD  ; 這個就和#dfine不一樣了意義上面說過

    VARB DB 2 DUP(?)

  

  (5) 等于語句 =

     符號名 = 數(shù)值表達式

    其實就是專用的 EQU,功能和EQU是一樣的,只不過試用范圍比EQU小,只能用在數(shù)值表達式上

    x = 10 ;? x equ 10

    y =20 +50*60 ; y equ 20+50*60

  

  (6) 定義符號名語句

    符號名 LABEL 類型

    類型可以是 BYTE WORD DWORD NEAR FAR

    他的作用其實應該是包含上面 this 指令中的用法即

      my_byte equ this byte

      my_word dw 8 dup(?)

      換成LABEL的寫法就是    

      my_byte label byte 

      my_word dw 8 dup(?)

?

   同時LABLE 還比this強大就是還能作用在標號上

   quit label far

   exit: mov ah,4ch

   這樣的用法就 mov ah,4ch這條指令同時擁有 exit的短調(diào)指令和quit的長跳指令了。

?

?  (7) 變量和標號的屬性

    變量和標號的屬性無非就是對應的類型 地址 大小等,對應的操作符

    LENGTH SIZE OFFSET SEG TYPE PTR

    seg 返回變量或標號的段地址    假設 VAR 的地址是 100+2? ?那么mov al, seg var ; al=100

    offset 返回變量或標號的偏移地址  假設 VAR 的地址是 100+2? ?那么mov al, offset var ; al=2

    type 返回變量或標號的類型   字節(jié)=1 字=2 雙字=3 近=-1 遠=-2,變量類型就是實際占用的字節(jié)數(shù)

    length 返回的是DUP定義的長度  DUP將在下面講到, 注意這里返回的是個數(shù),如果數(shù)組沒用DUP那么總是返回1 如果嵌套了就返回最外層的

    size? 返回DUP定義的實際占用字節(jié)數(shù)

    ptr? 強制類型轉(zhuǎn)化 就是C語言中的(int)A;的作用 用法就是? ? ?類型 ptr? 變量/數(shù)據(jù)地址? 類型可以是 byte word dword near far

        例如:

        mov word ptr [si],1

        jmp far ptr ok

?

優(yōu)先級

   1. 各種括號,LENGTH SIZE WIDTH MASK

   2. PTR OFFSER SEG TYPE THIS 冒號

   3. * / shl shr

   4. HIGH LOW

   5. + -

   6. eq ne lt le gt ge

   7. not

   8. and

   9. or, xor

   10. short

?

程序組織偽指令

  這些指令是為了方便匯編程序的結(jié)構(gòu)組織的

  (1) 段定義語句

    為了與存儲器的分段結(jié)構(gòu)相對應,所以匯編指令也提供了對應的段的組織方式

    段的開始

      段名 SEGMENT [定位類型] [組合類型] [‘類別’]

      。。

    段的結(jié)束

      段名?ENDS

?

    例子

    ;數(shù)據(jù)段

    DSEG SEGMENT

    MESS DB 'HELLO'

    DSEG ENDS

    ;代碼段

    CSEG SEGMENT

      MOV AX, DSEG

        ...

        ...

    CSEG ENDS

?

  (2) 段使用設定語句

    ASSUME 段寄存器名: 段名 [, 段寄存器名: 段名,?段寄存器名: 段名 ..]

    設定了段之后匯編程序需要知道各自段對應是用來干嘛的,并設置對應的段寄存器。ASSUME就是這個作用

    ASSUME CS: CSEG,DS:DSEG

    ASSUME 是偽指令所以匯編編譯器其實是將其轉(zhuǎn)換成了對應的匯編指令,所以ASSUME可以出現(xiàn)在代碼段的任何位置。隨時進行切換

    這里有個需要注意的是,如下代碼

    DSGE1?SEGMENT

        .....

    DSGE ENDS

?

    DSEG2 SEGMENT

        ......

    DSGE2 ENDS

?

    CSEG SEGMENT

    ASSUME CS:CSEG DS:DSEG1 ES:DSEG2

    MOV AX,DSEG1      ; 由于此時數(shù)據(jù)段就是DSEG1 所以指令就是直接翻譯的

    MOV AX,DSEG2      ; 由于此時數(shù)據(jù)段是DSEG1,所以實際語句會被翻譯成 MOV AX, ES:DSEG2

?

  (3) ORG 指令

    ORG 數(shù)值表達式

    匯編編譯器在匯編的時候使用匯編地址計算器來計算每條指令的偏移地址,而ORG指令就是用于手動修改當前地址的

    比如

    test segment

       org 100h

    begin: mov ax,1234h

    test ends

    mov ax,1234h 是段內(nèi)的第一條語句偏移應該是0 ,但是由于ORG 100H的緣故,實際的偏移地址就變成了100H

  

  (4) 當前地址 $

    $表示當前指令的第一個字節(jié)的地址

    org $+8 表示表示地址計算器從此處開始向后空8個字節(jié)出來

    他也可以用在其他指令中,比如

    jmp? $+ 6 ; 轉(zhuǎn)跳到本條指令之后6個字節(jié)處,注意計算地址是JMP指令的開始位置不是結(jié)束位置,所以這6個自己包含了JMP本身的長度

    ARRAY 1,2,$+4; 這里的% 表示的是ARRAY的地址不是 $ +4的地址

?

轉(zhuǎn)載于:https://www.cnblogs.com/alwaysking/p/7623781.html

總結(jié)

以上是生活随笔為你收集整理的汇编学习笔记(4)-伪指令(MASM)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。