数据传送、寻址和算术运算

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汇编语言程序设计学习-第四章 数据传送、寻址和算术运算-上相关推荐

  1. Intel汇编语言程序设计学习-第三章 汇编语言基础-下

    3.4  定义数据 3.4.1  内部数据类型 MASM定义了多种内部数据类型,每种数据类型都描述了该模型的变量和表达式的取值集合.数据类型的基本特征是以数据位的数目量的大小:8,16,32,,48, ...

  2. Intel汇编语言程序设计学习-第六章 条件处理-上

    条件处理 本章要点 1.简介 2.布尔和比较指令 3.条件跳转 4.条件循环指令 5.条件结构 6.应用:有限状态机 7.决策伪指令 6.1  简介 本章,读者将看到高级条件分支如何翻译成底层的实现代 ...

  3. Intel汇编语言程序设计学习-第五章 过程-下

    5.3.3  库测试程序 测试程序#1:整数I/O 该测试程序把输出文本的颜色改为蓝底黄字,然后以十六进制数显示七个数组的内容,最后提示用户输入一个有符号整数,再分别以十进制.十六进制和二进制格式重复 ...

  4. Intel汇编语言程序设计学习-第五章 过程-上

    过程 5.1  简介 需要阅读本章的理由可能很多: 1.读者可能想要学习如何在汇编语言中进行输入输出. 2.应该了解运行时栈(runtime stack),运行时栈是子过程(函数)调用以及从子过程返回 ...

  5. Intel汇编语言程序设计学习-第三章 汇编语言基础-中

    3.2  例子:整数相加减 现在来看一个进行整数加减操作的汇编语言小程序.寄存器用于存放中间数据,我们调用一个库函数在屏幕上显示寄存器的内容.下面是程序的源码: TITLE Add and Subtr ...

  6. Intel汇编语言程序设计学习-第三章 汇编语言基础-上

    汇编语言基础 3.1  汇编语言的基本元素 有人说汇编难,有人说汇编简单,我个人不做评价,下面是一个简单的实例(部分代码): main PROC mov  eax,5  ;5送EAX寄存器 add   ...

  7. Intel汇编语言程序设计学习-第六章 条件处理-中

    6.3  条件跳转 6.3.1  条件结构 在IA-32指令集中没有高级的逻辑结构,但无论多么复杂的结构,都可以使用比较和跳转指令组合来实现.执行条件语句包括两个步骤:首先,使用CMP,AND,SUB ...

  8. Intel汇编语言程序设计学习-第六章 条件处理-下

    6.6  应用:有限状态机 这个东西说了半天,感觉就是把逻辑弄得跟有向图一样,没看出来什么高端的东西,下面就整理下书上说的概念: 有限状态机(FSM,Finite-State Machine)是依据输 ...

  9. Intel汇编语言程序设计学习-第一章 基本概念

    第一章基本概念 1.1  简单介绍 本书着重讲述MS-Windows平台上IA-32(Intel Architecture 32bit,英特尔32位体系架构)兼容微处理器的汇编语言程序设计,可以使用I ...

最新文章

  1. 【干货】连交换机的攻击、防御都不懂,还做什么网络工程师
  2. 【详细解读】进程管理 -死锁问题 系统有三个进程:A B C 这3个进程都需要5个系统资源。如果系统至少有多少个资源,则不可能发生死锁
  3. apt-get clean 清除 apt 的缓存
  4. 华为反击!要求美国运营商巨头支付 10 亿美元专利费!
  5. tum数据集_数值预报尚能战否?来自数据驱动的挑战
  6. 普通人创业做生意,送你三千万
  7. Zabbix 5.0 配置简单WEB网页监测和触发器
  8. FAQ系列 | 用MySQL实现发号器
  9. multisim中pwl_multisim元器件
  10. Matlab标定工具箱使用教程
  11. 可以打印快递电子面单的表格
  12. 【Redis】Failed listening on port 6379 (TCP), aborting.
  13. Pr混剪视频制作教程[纯萌新]
  14. 付费学习,花钱比意志力靠谱
  15. AndroidStudio配置LitePal时Failed to Resolve
  16. 微服务之服务监控篇 ActuatorAdmin
  17. 我的经历---公司破产
  18. P4098 [HEOI2013]ALO
  19. MTK平台LK中的APP_START(LK app service)介绍
  20. 【工具】监听手机短信转发到群聊或服务器

热门文章

  1. 简单的Tab切换组件
  2. 监控录像帮忙找回医院被偷的女婴
  3. symfony的安装方法
  4. mongodb模糊查询包含特殊字符
  5. 如何查看表和索引的统计信息
  6. MySQL备份工具收集
  7. ubuntu16.04服务器配置mysql,并开启远程连接
  8. 网络数据的XML解析
  9. Oracle面试过程中常见的二十个问题
  10. 都都的第一次自我游戏