Intel汇编语言程序设计学习-第四章 数据传送、寻址和算术运算-上
數據傳送、尋址和算術運算
4.1 ?數據傳送指令
4.1.1 ?簡介
? ? 第一段一大推,就是為了說明匯編相比高級語言來說比較麻煩需要注意很多細節,但是換來的好處是給開發者帶來了更大的靈活性。
讀者如果肯花時間徹底掌握本章內容,那么本書的后續部分將更容易學習。對以后變得越來越復雜的例子程序的理解,將在很大程度上依賴于對本章提供的基本工具的掌握。
4.1.2 ?操作數類型
? ? 本章講述三種類型的操作數:立即操作數(immediate)、寄存器操作數(register)和內存操作數(memory)。在這三者當中,只有內存操作數稍微有點復雜。下表列出的操作數的簡寫符號是從Intel IA-32手冊上摘錄下來的。
?
4.1.3 ?直接內存操作數
? ? 3.4節已經解釋過,變量名僅僅是對數據段內偏移地址的引用。下面的聲明表示一個包含數字10h的字節被置于數據段內:
.data
var1 BYTE 10h
? ? 指令使用內存操作數時實際上使用的書操作數的地址。假設var1位于偏移10400h處,那么把var1送AL寄存器的匯編指令如下:
mov AL,var1
MASM將這條指令匯編成如下的機器指令:
A0 00010400
? ? 機器指令的第一個字節是操作碼,剩下的部分是變量var1的十六進制的32位地址值。編寫程序時僅使用純數字地址表示內存操作是可以的,不過像var1這樣的符號名使得引用內存時更加方便一些。
一些開發者更喜歡使用下面的方式表示直接操作數,因為方括號按時了要進行尋址操作:
mov al,[var1]
MASM允許使用這種方式。mov al,[var1+5] (這稱為直接偏移操作數。)
4.1.4 ?MOV指令??
? ? MOV指令從源操作數向目的操作數復制數據。作為數據傳送指令,幾乎每個程序中都會用到MOV。其基本格式是:第一個操作數是目的(destination)操作數,第二個操作數是源(source)操作數:
MOV destination,source
指令運行后,目的操作數的內容被改變而源操作數的內容保持不變。
MOV指令對操作數的使用是非常靈活的,只要遵循以下規則即可:
1.兩個操作數的尺寸必須一致。
2.兩個操作數不能同時為內存操作數。
3.目的操作數不能是CS,EIP和IP。
4.立即數不能直接送至段寄存器。
下面是MOV指令格式列表,但寄存器(reg)是不包括段寄存器的:
????MOV reg ?,reg
????MOV mem ,reg
????MOV reg ?,mem
????MOV mem ,imm
????MOV reg ?,imm
? ? 在運行于保護模式下時,程序不應直接修改段寄存器。一般來說,段寄存器僅應由實地址模式下運行的程序使用,對段寄存器的操作可以有一下兩種格式,唯一的例外是CS不能用作目的操作數:
MOV ?r/m16 ,sreg
MOV ?sreg ,r/m16
????內存之間的移動:單條MOV指令不能把數據從一個內存位置直接移動到另外一個內存位置。
作為一種替代方法,在送至目的操作數之前,可以先把源操作數移入一個寄存器中:
.data
??var1 WORD ?
??var2 WORD ?
.code
??mov ax ,var1
??mov var2,ax
?
4.1.5 ?整數的零/符號擴展
復制較小值至較大值中
盡管不能直接使用MOV指令把數據從一個尺寸較小的操作復制到一個尺寸較大的操作數中,但有時確實需要這樣的移動數據。例如,假設字count(無符號16位數)必須送到ECX(32位)中,一個簡單的解決方法是先把ECX清零,然后再把count送到CX中:
??.data
??count WORD 1
??.code
??mov ecx ,0
??mov cx,count
但是注意一個問題,就是操作負數的時候會有問題。如:
??.data
??signedVal SWORD -1
??.code
??mov ecx ,0
??mov cx,signedVal
這種情況,我們可以以FFFFFFFFh填充ECX,然后復制signedVal至CX中,那么最終結果將是正確的:
.data
signedVal SWORD -1
signedVa2 SDWORD 0
.code
mov ecx ,0FFFFFFFFh
mov cx,signedVal
mov signedVa2,ecx
?
這樣雖然可以解決問題,但是比較麻煩,所以引入了MOVZX和MOVSX指令,已處理有符號和無符號整數。
MOVZX指令
MOVZX(move with zero-extend,零擴展傳送)指令將源操作數的內容復制到目的操作數中,并將該值擴展(zero-extend)至16位或32位。該指令僅適用于無符號整數,它有如下三種格式:
Movzx r32 ,r/m8
Movzx r32,r/m16
Movzx r16,r/m8
在此三種格式中第一個操作數是目的操作數而第二個操作數是源操作數,目的操作數必須是寄存器。下面的指令把二進制10001111送AX:
mov b1 ,10001111b
movzx ax,bl
下圖解釋了8位源操作數是如何擴展成16位目的操作數的:
?
下面的例子中所有的操作數全部使用寄存器,演示了所有可能的尺寸格式組合:
?
下面的例子使用內存操作數作為源操作數,產生的結果同上:
?
MOVSX指令
和movzx指令類似,但是它是處理有符號整數的。
?
4.1.6 ?LAHF和SAHF指令
LAHF(load status flags into AH)指令將EFLAGS寄存器的低字節復制到AH寄存器,被復制的標志包括:符號標志、零標志、輔助進位標志、奇偶標志和進位標志。使用該指令可以方便地將標志值保存在變量中:
.data
saveflags BYTE 0
b1 BYTE 0
.code
LAHF
mov saveflags ,ah
SAHF(store AH into status flags)指令復制AH寄存器的值至EFLAGS寄存器的低字節,例如,可以用如下指令回復剛才保存在變量中的標志:
mov ah ,saveflags
SAHF
4.1.7 ?XCHG指令
XCHG(exchange data)指令交換兩個操作數的內容,它有下面三種格式:
XCHG reg,reg
XCHG reg,mem
XCHG mem,reg
XCHG指令不接受立即數操作數,除此點不同之外,XCHG指令的操作數與MOV指令的操作數遵循同樣的規則。在用到數組排序的應用程序中,XCHG指令提供了交換連個數組元素的簡便方法,以下是一些使用XCHG指令的例子:
??xchg ax,bx ?;交換兩個16位寄存器的內同
??xchg ah,al ?;交換兩個8位寄存器的內容
??xchg var1,bx;交換16位的內存操作數和BX寄存器內容
??xchg eax,ebx;交換兩個32位寄存器的內同
若要交換兩個內存操作數,需要使用一個寄存器作為臨時存儲容器,并把mov指令和xchg指令結合起來使用:
mov ?ax ,val1
xchg ax ,val2
mov ?val1 ,ax??
4.1.8 ?直接偏移操作數
在變量名稱后加上一個偏移值,可以創建直接偏移(direct-offset)操作數,可以通過它來訪問沒有顯示標號的內存地址。我們以一個名為arrayB的字節數組開始枚舉:
.data
arrayB BYTE 10h ,20h ,30h ,40h ,50h
.code
mov al ,arrayB
mov al ,[arrayB+1]
mov al ,[arrayB+2]
如果是雙字節或者是其他,注意偏移的時候地址是2或者其他等,比較簡單不細說了。
????范圍檢查:MASM不對有效地址進行范圍檢查,對下面的語句,匯編器將原樣翻譯。如果執行下面的語句,就能夠取得數組之外的一個內存字節。這可能會造成一個非常隱蔽的邏輯錯誤,因此開發者在檢查對數組的引用時應該格外小心
4.1.9 ?例子程序(數據傳送)
算是對4.1的一個總結
TITLE Data Transfer Examples ?(Moves.asm)
INCLUDE Irvine32.inc
.data
val1 WORD 1000h
val2 WORD 2000h
arrayB BYTE 10h ,20h ,30h ,40h ,50h
arrayW WORD 100h ,200h ,300h
arrayD DWORD 10000h ,20000h
.code
main PROC
;MOVZX
????mov ??bx ,0A65Bh ??????
????movzx eax,bx ???????????;EAX = 0000A64Bh
movzx cx ,bl ???????????;CX = 009Bh
;MOVSX
????mov ??bx ,0A69Bh
movsx eax,bx ???????????;EAX = FFFFA69Bh
movsx edx,bl ???????????;EDX = FFFFFF9Bh
mov ??bl,7Bh
movsx cx,bl ????????????;CX = 007Bh
;內存到內存的交換
????mov ??ax ,val1 ?????????;AX = 1000h ???????
xchg ?ax ,val2 ?????????;AX=2000h ,val2=1000h
mov ??val1 ,ax ?????????;val1 = 2000h
;直接偏移尋址(字節數組)
????mov al ,arrayB ?????????;AL = 10h
mov al ,[arrayB+1] ?????;AL = 20h
mov al ,[arrayB+2] ?????;AL = 30h
;直接偏移尋址(字數組)
????mov ax ,arrayW ?????????;AX = 100h
mov ax ,[arrayW+2] ?????;AX = 200h
????exit
main ENDP
END main
4.2 ?加法和減法
本章著重講述整數的加法和減法;第7張講述整數的乘法和出發;第17章介紹如何進行浮點運算,使用另外一套與整數運算完全不同指令。
4.2.1 ?INC和EDC指令
INC(increment)和DEC(decrement)指令從操作數中加1或減1,格式是:
INC ?reg/mem
DEC ?reg/mem
下面是一些例子:
.data
myWord WORD 1000h
.code
Inc ??myWord ?;4097 并不是1001h 書上寫錯了
mov ?bx ,myWord
dec ??bx ??????;1000h ?
4.2.2 ?ADD指令
ADD指令將同尺寸的源操作數和目的操作數相加,格式是:
ADD 目的操作數,源操作數,例子:
.data
var1 DWORD 10000h
var2 DWORD 20000h
.code
mov eax ,var1 ?;EAX = 10000h
add eax ,var2 ?;EAX = 30000h
4.2.3 ?SUB指令
SUB指令將源操作數從目的操作數中減掉,操作數格式與ADD和MOV指令操作數相同。
SUB 目的操作數 ,源操作數
例子:
.data
var1 DWORD 30000h
var2 DWORD 10000h
.code
mov eax ,var1 ?;EAX = 30000h
sub eax ,var2 ?;EAX = 20000h
有一種執行減法而無需使用額外的數字電路單元的簡單方法:對源操作數求補,然后把源才做書和目的操作數相加。例如4-1可以看做是 4 + (-1)
?
影響的標志:SUB指令根據目標操作數的值相應的修改進位標志、零標志。符號標志、溢出標志、輔助進位標志和奇偶標志。
4.2.4 ?NEG指令
NEG(negate)指令通過將數字轉換為對應的補碼而求得其相反數:
NEG reg
NEG mem
4.2.5 ?實現算術表達式
Rval = -Xval + (Yval - Zval);
匯編實現
.data
Rval SDWORD ?
Xval SDWORD 26
Yval SDWORD 30
Zval SDWORD 40
.code
?mov eax ,Xval
?neg eax
?mov ebx ,Yval
?sub ebx ,Zval
?add eax ,ebx
?mov Rval ,eax
4.2.6 ?加法和減法影響的標志位
略
4.2.7 ?例子程序(AddSub3)
TITLE Addition and Subtraction ?(AddSub3.asm)
INCLUDE Irvine32.inc
.data
Rval SDWORD ?
Xval SDWORD 26
Yval SDWORD 30
Zval SDWORD 40
.code
main PROC
;INC and DEC
??mov ?ax ,1000h
??inc ?ax ???????????;1000h + 1
??dec ?ax ???????????;1000h
;Rval = -Xval + (Yval - Zval)
??mov ?eax ,Xval
??neg ?eax
??mov ?ebx ,Yval
??sub ?ebx ,Zval
??add ?eax ,ebx
??mov ?Rval ,eax
;零標志的例子
??mov ?cx ,1
??sub ?cx ,1 ??????????;ZF = 1
??mov ?ax ,0FFFFh ???
??inc ?ax ?????????????;ZF = 1
;符號標志的例子
??mov ?cx ,0
??sub ?cx ,1 ??????????;SF = 1
??mov ?ax ,7FFFh
??add ?ax ,2 ??????????;SF = 1
;進位標志的例子
??mov al ,0FFh
??add al ,1 ???????????;OF = 1
??mov al ,-128
??sub al ,1 ???????????;OF = 1
?
??exit
main ENDP
END main
?
?
?
總結
以上是生活随笔為你收集整理的Intel汇编语言程序设计学习-第四章 数据传送、寻址和算术运算-上的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Intel汇编语言程序设计学习-第三章
- 下一篇: 汇编环境搭建(vs2010(2012)+