数据传送和运算操作--《32位汇编语言程序设计》

郑州大学汇编语言程序设计基础教程
文章介绍了汇编语言中的基本指令,如MOV用于数据传送,XCHG用于交换操作数内容,NOP为空操作,LEA用于获取存储器操作数的地址。还讲解了堆栈的工作原理和PUSH、POP指令,以及加法、减法、乘法、除法等运算指令及其对状态标志的影响。

欢迎来看郑州大学汇编语言程序设计课程[doge]

传送指令

MOV指令

数据传送把数据从一个位置传送到另外一个位置,是计算机中最基础也是程序设计中最常用的指令。

除了标志寄存器传送指令外,均不影响状态标志。

MOV指令功能

上面图片展示了MOV操作指令的作用,即将源操作数传送到目的操作数的位置,此传送是复制传送,源操作数仍旧存在。

mov指令的用法

上面的图片展现了mov指令源操作数和目的操作数的可选情况,其中立即数不能做目的操作数,段寄存器和主存储器不能够同时为源操作数目的操作数。

cpu不能够同时访问同一个内存单元

mov al,200
mov ax,200
mov eax,200
;三种长度的传送,由于源操作数为立即数,因此传送的长度以目的操作数而定
mov bvar,byte ptr 200
mov [eax],word ptr 200
mov [esi+8],dword ptr 200
;按照指定长度进行数据的传送

常见语法错误

  • 要注意源操作数和目的操作数的类型必须一致
  • 源操作数和目的操作数不能够同时没有明确的数据类型
  • 注意存储器相对寻址时,若偏移量有数据类型,那么这个寻址数据就有数据类型。
  • CPU不能够同时访问内存单元(不能同时读写内存单元)
  • 立即数不能直接传送段寄存器,对于段寄存器,不能够直接赋值,需要使用寄存器等中转一下
  • 对于指令指针寄存器EIP,没有对其显示的操作指令,基本上不允许用户直接对他操作

XCHG指令

  • 将源操作数和目的操作数内容互换
  • 但是仅支持通用寄存器和存储器两种类型
  • 源操作数和目的操作数不能够同时为存储器寻址
  • 三种数据类型均支持

如下面的例子:

dvar dword 12345678H
mov al,byte ptr dvar
xchg al,byte ptr dvar+3
mov byte ptr dvar,al

mov al,byte ptr dvar+1
xchg al,byte ptr dvar+2
mov byte ptr dvar+1,al

首先将dvar变量的低8位移到通用寄存器中,然后将通用寄存器内容与变量高8位互换,最后再将通用寄存器内容放至变量低8位,即实现了变量高八位与低八位的互换。最后对于中间的十六位采用同样的方式进行互换,最后就完成了此变量小端存储方式和大端存储方式的互换。

NOP

这是一条空操作指令,没有什么实际的操作,等价于:

xchg eax,eax

但是这条指令的执行需要花费时间,并且占用一个字节的存储空间,可以使用NOP空操作指令来达到一个延时的效果,并且可以临时先占用代码的空间

LEA指令

  • 这是一个地址传送指令,用来获取存储器操作数的地址
LEA r16/r32,mem

可以将存储单元的有效地址放到十六位或者三十二位寄存器中

LEA与offset的区别

  • offset指令是在汇编阶段获取变量的偏移地址 而lea指令是在执行到这条语句时计算出偏移地址
  • 因此offset指令更加快速,但是不如lea机动性强,对于一开始无法确定偏移地址的来讲需要使用lea指令,对于可以得来讲,使用offset要快
  • lea指令在计算地址时可以进行加和位移操作而offset不能够这样使用

堆栈

  • FILO存取原则

IA-32处理器在主存空间构建堆栈段

  • 堆栈段寄存器SS指向堆栈段的起始位置
  • 堆栈指针寄存器ESP指向当前栈顶

数据传输通过当前堆栈的栈顶,传输过程中栈顶会发生改变

而对于IA-32处理器,特殊的地方在于,这个堆栈是向下生长的,上面(高地址)是栈底,下面(低地址)作为栈顶。当使用PUSH压栈时ESP栈顶指针减小,使用POP弹出数据,栈顶指针ESP变大。

堆栈的作用

PUSH和POP指令

PUSH

push r16/m16/i16/seg
push r32/m32/i32

push指令可以将十六位或者三十二位的寄存器、存储器数据或者立即数,以及段寄存器数据压到栈中。

其原理是,先将栈顶指针ESP根据操作数的数据类型减2或者减4,然后将栈顶指针ESP所指的内存单元赋为操作数的值。

下面是几个例子:

push eax
;等同于下面两个指令
sub esp,4
mov [esp],eax

POP

同PUSH,减变为加

把当前栈顶的数据弹出给操作数

pop eax
;等同于下面两个指令
mov eax,[esp]
add esp,4

运算指令

状态标志是处理器最基本的标志

  • 作为加减运算和逻辑运算的辅助结果
  • 构成各种条件、实现程序分支

进位标志CF(Carry Flag)

当加减运算结果最高位有进位的时候或者有借位的时候,进位标志置为1,否则的话为0

对于无符号整数,这个标志为可以用来判断结果是否超出表达范围
[ 0 , 2 N − 1 ] [0,2^{N}-1] [0,2N1]

溢出标志OF(Overflow Flag)

用来表示有符号整数的运算结果是否有溢出,即加减结果是否超出表达范围,溢出置为1否则为0
[ − 2 N − 1 , 2 N − 1 − 1 ] [-2^{N-1},2^{N-1}-1] [2N1,2N11]
同符号数相加减结果符号位改变则溢出

零标志ZF(Zero Flag)

结果为0,ZF=1否则为0

符号位SF(Sign Flag)

运算结果最高位为1,则SF=1否则为0

奇偶标志PF(Parity Flag)

当运算结果的低八位中1的个数为偶数或0个时,PF=1否则为0

ADD指令

add reg,imm/reg/mem
add mem,imm/reg

加法指令令目的操作数加上源操作数赋值给目的操作数

  • 按照定义影响状态标志位

SUB指令

sub reg,imm/reg/mem
sub mem,imm/reg

减法指令将目的操作数减去源操作数然后结果赋值给目的操作数

  • 按照定义影响状态标志位

ADC指令

带进位的加法指令,

如下面的例子计算六十四位加运算:

mov eax,dword ptr qvar1
add eax,dword ptr qvar2
mov edx,dword ptr qvar1+4
adc edx,dword ptr qvar2+4

首先取六十四位的低三十二位进行add加法运算,然后如果这个运算有了进位,CF就会被设置为1,然后取高三十二位进行adc带标志位的加法运算,最后就完成了六十四位的加法运算

SBB指令

同adc一样,先取第三十二位sub相减,然后再高三十二位sbb相减

INC指令

增量指令(increment)

  • 不影响进位标志,但是影响其他标志
INC reg/mem

经常用于计数器和地址指针的调整

DEC指令

减量指令(decrement)

同INC不过是自减

NEG指令

对操作数执行求补运算,即用0减去操作数

NEG reg/mem

对标志位的影响与减法指令sub一样

可用于对负数的求补或者由补码求其绝对值

MUL与IMUL乘法指令

MUL reg/mem;无符号整数乘法指令
IMUL reg/mem;有符号整数乘法指令

上面的乘法运算只有一个操作数,实际上进行操作的时候是借用了寄存器。以八位乘法为例,我们可以先将一个八位乘法的数据存储到AL寄存器中,然后再使用MUL指令对另一个八位数据操作,最后乘法的结果会保存到AX寄存器中。

以上的双操作数指令和三操作数指令,第一个操作数都是指定存放结果数据的位置,只能够是通用寄存器,并且我们要保证指定的寄存器要放得下乘积的结果

双操作数是两个操作数相乘放到目的操作数位置

三操作数是后两个操作数相乘放到目的操作数位置

DIV与IDIV除法指令

商的符号和除数的符号一致,余数的符号和被除数的符号一致

零位扩展

无符号数零位扩展前面加0实现

零位扩展指令MOVZX

前面补零放到目的寄存器中

movzx r16,r8/m8
movzx r32,r8/r16/m8/m16

符号扩展指令MOVSX

符号扩展前面加符号位扩展

movsx r16,r8/m8
movsx r32,r8/m8/r16/m16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_南明_离火_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值