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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Intel汇编语言程序设计学习-第四章 数据传送、寻址和算术运算-上

發布時間:2025/6/17 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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處,那么把var1AL寄存器的匯編指令如下:

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,EIPIP

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位數)必須送到ECX32位)中,一個簡單的解決方法是先把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,然后復制signedValCX中,那么最終結果將是正確的:

.data

signedVal SWORD -1

signedVa2 SDWORD 0

.code

mov ecx ,0FFFFFFFFh

mov cx,signedVal

mov signedVa2,ecx

?

這樣雖然可以解決問題,但是比較麻煩,所以引入了MOVZXMOVSX指令,已處理有符號和無符號整數。

MOVZX指令

MOVZXmove with zero-extend,零擴展傳送)指令將源操作數的內容復制到目的操作數中,并將該值擴展(zero-extend)至16位或32位。該指令僅適用于無符號整數,它有如下三種格式:

Movzx r32 ,r/m8

Movzx r32,r/m16

Movzx r16,r/m8

在此三種格式中第一個操作數是目的操作數而第二個操作數是源操作數,目的操作數必須是寄存器。下面的指令把二進制10001111AX:

mov b1 ,10001111b

movzx ax,bl

下圖解釋了8位源操作數是如何擴展成16位目的操作數的:

?

下面的例子中所有的操作數全部使用寄存器,演示了所有可能的尺寸格式組合:

?

下面的例子使用內存操作數作為源操作數,產生的結果同上:

?

MOVSX指令

movzx指令類似,但是它是處理有符號整數的。

?

4.1.6 ?LAHFSAHF指令

LAHFload status flags into AH指令將EFLAGS寄存器的低字節復制到AH寄存器,被復制的標志包括:符號標志、零標志、輔助進位標志、奇偶標志和進位標志。使用該指令可以方便地將標志值保存在變量中:

.data

saveflags BYTE 0

b1 BYTE 0

.code

LAHF

mov saveflags ,ah

SAHFstore AH into status flags指令復制AH寄存器的值至EFLAGS寄存器的低字節,例如,可以用如下指令回復剛才保存在變量中的標志:

mov ah ,saveflags

SAHF

4.1.7 ?XCHG指令

XCHGexchange 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 ?INCEDC指令

INCincrement)和DECdecrement)指令從操作數中加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指令將源操作數從目的操作數中減掉,操作數格式與ADDMOV指令操作數相同。

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指令

NEGnegate)指令通過將數字轉換為對應的補碼而求得其相反數:

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汇编语言程序设计学习-第四章 数据传送、寻址和算术运算-上的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。