汇编学习笔记(4)-伪指令(MASM)
前言
編寫匯編代碼的時候會使用到兩種語句,一種就是前面介紹的匯編指令又CPU提供功能支持,另一種呢叫做偽指令,偽指令是由匯編的編譯器提供支持。所以偽指令的運行結果都必須實在編譯的時候就能確定的,下面介紹的就是偽指令了。
注意接下來介紹的偽指令都是基于MASM匯編編譯器,比較常用的還有NASM 它的語法以后有機會介紹
?
數值表達式
數值表達式不是匯編指令,表達式的值是在匯編代碼的匯編過程中就由匯編編譯器計算出結果而寫到二進制程序中了,并不是在程序運行的過程中才計算的
(1) 常數表達式
常數就是直接的數字,直接寫數字默認表示10進制數,也可以用符號指定為其他進制
D = 十進制 ; MOV AL, 1234D
B = 二進制 ; MOV AL,? 0101B
H = 十六進制 ; MOV AL,? 0FFFFH , 注意常數必須是數字開頭不能是字母開頭,如果16進制數第一個數字是字母的話就要補一個0在前面
Q = 八進制 ; MOV AL, 123Q
?
因為在程序中字母也是數字,所以其實也可以直接將字母或者字符串當成數字,比如
MOV AL, 'a'
MOV AX,"ab" ; 雙引號和單引號都是可以使用的
?
? (2) 算數運算符
就是簡單的 正(+) 負(-) 加(+) 減(-) 乘(*) 除(/) 模(mod)
mov ax, 100+200
mov ax, 100/2
?
(3) 關系運算符
等于(EQ) 不等(NE) 大于(GT) 小于(LT) 大于等于(GE) 小于等于(LE)
如果等式成立則實際的值為0FFFF就是補碼表示的-1, 如果關系不成立那么結果就是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 表示取數據的高八位
LOW 表示取數據的低八位
??
地址表達式
地址表達式所表示的是存儲器操作數的地址。前面介紹的各種尋址方式實際上也是地址表達式。
一般格式是
mov ax, varw+4
?
注意 varw 變量或者標號的地址,這個是在編譯的時候就知道的,所以varw+4 計算出來的就是varw 地址偏移4的地址,所以AX的值不是 varw+4的值,而是varw+4 內存地址處的值,所以AX的值是不確定的。
當然還有其他的寫法
[varw+bx]
varw[bx]
varw[bx+di]
varw[bx][di]
?
變量和標號
(1) 數據定義語句
[變量名]? 變量類型 表達式[, 表達式]
其中變量類型有
DB 字節
DW 字
DD? 雙字
所以數據定義就可以是這樣的
a db 1,2,3,4,5
db 7,8,9,10
b dw 123,123,123
c dd 123,?,?,?
?
匯編中的數據定義意義其實就是C中的數組指針。這些數據都是順序存放在內存中的,所以雖然第二行的數據沒有定義名字,但是因為他緊跟在a 數組之后 b數組之前,所以使用a+5,或者 b-1 也是可以訪問的,只是需要注意的是數據類型和 大端小端的問題。
后面跟實際數據的就表示定義的時候就直接初始化了數據,如果只是想留著位置,并不需要初始化的話也可以使用? 表示,?的意思就是只留位置不初始化內容
前面也說過,字符其實也可以表示為數字,所以也之后直接定義字符數組,下面的兩種方式都是可行的
str? db “hello”
str db "h","e","l","l","0"
(2) 循環定義 DUP
數字表達式 DUP(數據[, 數據,數據...])
有時候定義數組只是想預留一些空間,可能需要預留100個字節那么使用
buff db ?,?,?,?.......??
這種方式要打100個? 這樣顯然很沒效率所以有個偽指令可以幫忙
buff db 100 dup(?); 定義100個DB 數據不用初始化
也可以這樣
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數組等效的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) 等于語句 =
符號名 = 數值表達式
其實就是專用的 EQU,功能和EQU是一樣的,只不過試用范圍比EQU小,只能用在數值表達式上
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的短調指令和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 返回變量或標號的類型 字節=1 字=2 雙字=3 近=-1 遠=-2,變量類型就是實際占用的字節數
length 返回的是DUP定義的長度 DUP將在下面講到, 注意這里返回的是個數,如果數組沒用DUP那么總是返回1 如果嵌套了就返回最外層的
size? 返回DUP定義的實際占用字節數
ptr? 強制類型轉化 就是C語言中的(int)A;的作用 用法就是? ? ?類型 ptr? 變量/數據地址? 類型可以是 byte word dword near far
例如:
mov word ptr [si],1
jmp far ptr ok
?
優先級
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
?
程序組織偽指令
這些指令是為了方便匯編程序的結構組織的
(1) 段定義語句
為了與存儲器的分段結構相對應,所以匯編指令也提供了對應的段的組織方式
段的開始
段名 SEGMENT [定位類型] [組合類型] [‘類別’]
。。
段的結束
段名?ENDS
?
例子
;數據段
DSEG SEGMENT
MESS DB 'HELLO'
DSEG ENDS
;代碼段
CSEG SEGMENT
MOV AX, DSEG
...
...
CSEG ENDS
?
(2) 段使用設定語句
ASSUME 段寄存器名: 段名 [, 段寄存器名: 段名,?段寄存器名: 段名 ..]
設定了段之后匯編程序需要知道各自段對應是用來干嘛的,并設置對應的段寄存器。ASSUME就是這個作用
ASSUME CS: CSEG,DS:DSEG
ASSUME 是偽指令所以匯編編譯器其實是將其轉換成了對應的匯編指令,所以ASSUME可以出現在代碼段的任何位置。隨時進行切換
這里有個需要注意的是,如下代碼
DSGE1?SEGMENT
.....
DSGE ENDS
?
DSEG2 SEGMENT
......
DSGE2 ENDS
?
CSEG SEGMENT
ASSUME CS:CSEG DS:DSEG1 ES:DSEG2
MOV AX,DSEG1 ; 由于此時數據段就是DSEG1 所以指令就是直接翻譯的
MOV AX,DSEG2 ; 由于此時數據段是DSEG1,所以實際語句會被翻譯成 MOV AX, ES:DSEG2
?
(3) ORG 指令
ORG 數值表達式
匯編編譯器在匯編的時候使用匯編地址計算器來計算每條指令的偏移地址,而ORG指令就是用于手動修改當前地址的
比如
test segment
org 100h
begin: mov ax,1234h
test ends
mov ax,1234h 是段內的第一條語句偏移應該是0 ,但是由于ORG 100H的緣故,實際的偏移地址就變成了100H
(4) 當前地址 $
$表示當前指令的第一個字節的地址
org $+8 表示表示地址計算器從此處開始向后空8個字節出來
他也可以用在其他指令中,比如
jmp? $+ 6 ; 轉跳到本條指令之后6個字節處,注意計算地址是JMP指令的開始位置不是結束位置,所以這6個自己包含了JMP本身的長度
ARRAY 1,2,$+4; 這里的% 表示的是ARRAY的地址不是 $ +4的地址
?
轉載于:https://www.cnblogs.com/alwaysking/p/7623781.html
總結
以上是生活随笔為你收集整理的汇编学习笔记(4)-伪指令(MASM)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Django扩展自定义manage命令
- 下一篇: 【河南省多校脸萌第六场 E】LLM找对象