汇编语言随笔(4)-数据段和栈段与mov,add,sub,div,mul、adc、sbb指令

      再次声明,默认采用小端法在内存中存储数据。

      在8086PC中,定位一个内存地址需要由段地址和偏移地址一起来完成。注意:当编写指令想要读取某个内存单元中的数据时,需要对偏移地址加上中括号’[ ]'。表示读取该地址上的数据。

数据段

      在编程时可以根据需要将一组内存单元定义为一个段。这段内存单元需要满足:代码长度不能大于64KB,必须是连续的内存单元,内存的起始地址为16的整数倍。当我们将数据存放在这样的内存单元中时,就可以将其定义为一个数据段。一般的,用DS来存放数据段的段地址,用BX来表示偏移地址

      如:将123B0H-123B9H内存单元定义为一个数据段。并且累加数据段中前三个字节单位中的数据。

	mov ax,123BH
	mov ds,ax     8086CPU不能直接将立即数传送到段寄存器中
	mov al,0
	add al,[0]
	add al,[1]
	add al,[2]

栈段

      在编程时可以根据需要将一组内存单元定义为一个段。这段内存单元需要满足:代码长度不能大于64KB,必须是连续的内存单元,内存的起始地址为16的整数倍。当我们要将这段内存单元作为栈空间来使用时,就可以认为它是一个栈段。用SS来存放栈段的段地址,用SP来指向栈顶。在任意时刻,SS:SP指向栈顶元素。

      入栈指令push,表示将某个数据压入栈中,操作对象大小必须为一个字。push ax的具体执行过程为:(1)SP=SP-2。(2)将ax中的内容送到SS:SP指向的内存单元处。入栈时,栈顶由高地址向低地址方向增长。

      出栈指令pop,表示从栈中弹出栈顶数据,操作对象大小必须为一个字。pop ax的具体执行过程为:(1)将SS:SP指向的内存单元处的数据送入ax。(2)SP=SP+2。出栈时,栈顶由低地址向高地址方向增长。

      例:若将10000H-1000FH这段空间看作为一个栈,初始状态栈为空。此时如果SS=1000H,那么SP=0010H

      注意:关于栈顶向上或向下超界的问题需要用户编程时自己注意。并且一个很有意思的点是:一个栈段的最大容量,亦或一个段的最大容量是64KB,这是由16位的偏移地址决定。如果一个栈段刚好是64KB时,即栈顶(偏移地址)变化范围为:0-FFFFH。首先当栈空时,SP为0000。随着不断有数据入栈,SP会不断减小,如FFFEH,FFFCH…0002H,0000H。我们可以发现当整个栈是满的的时候,SP也为0000。此时如果再有数据入栈,SP依然会不断减小,如FFFEH,FFFCH…0002H,0000H,也就是说新的数据会覆盖掉栈空间中以前的所有元素。

mov、add、sub指令

      mov指令使用形式如下:

指令 op1 op2 示例
mov 寄存器 数据 mov ax,8
mov 寄存器 寄存器 mov ax,bx
mov 寄存器 内存单元 mov ax,[8]
mov 内存单元 寄存器 mov [8],ax
mov 段寄存器 寄存器 mov ds,ax
mov 寄存器 段寄存器 mov ax,ds
mov 段寄存器 内存单元 mov ds,[8]
mov 内存单元 段寄存器 mov [8],ds
      add、sub指令使用形式如下:
指令 op1 op2 示例
add 寄存器 数据 add ax,8
add 寄存器 寄存器 add ax,bx
add 寄存器 内存单元 add ax,[8]
add 内存单元 寄存器 add [8],ax
sub 寄存器 数据 sub ax,8
sub 寄存器 寄存器 sub ax,bx
sub 寄存器 内存单元 sub ax,[8]
sub 内存单元 寄存器 sub [8],ax
      注意:不能将数据直接传送到段寄存器中;不能将段寄存器作为add/sub的操作对象。

div、mul指令

除法指令div

      除法规则:
      (1)除数:有8位或16位两种,可以放在reg或内存单元中。
      (2)被除数:默认放在AX或DX,和AX中,如果除数为8位,被除数则为16位,默认放在AX中;如果除数为16位,被除数则为32位,在DX和AX中存放,DX中存放高16位,AX中存放低16位。
      (3)结果:如果除数为8位,则AL存储除法操作的商,AH存储除法操作的余数;如果除数为16位,则AX存储除法操作的商,DX存储除法操作的余数;
      如:div bl      div bx      div byte ptr ds:[0]      div word ptr ds:[0]

乘法指令mul

      乘法规则:
      (1)两个相乘的数,要么都是8位,要么都是16位。如果是8位,一个默认放在AL中,另一个放在8位寄存器或内存字节单元中;如果是16位,一个默认放在AX中,另一个放在16位寄存器或内存字单元中
      (2)结果:如果是8位乘法,结果默认放在AX中;如果是16位乘法,结果的高位默认放在DX中,低位放在AX中;
      如:mul bl      mul bx      mul byte ptr ds:[0]      mul word ptr ds:[0]

add、sbb指令

      这两种指令均要用到标志寄存器中的cf标志位上的进位值或借位值。这两种指令的作用都是用来进行对大整数进行加减法操作的。

带进位加法指令adc

      指令格式:adc op1,op2效果为:op1=op1+op2+cf
      示例:对于0198H和0183H相加的运算
      (1)直接16位相加。
      指令为:mov ax,0198H      mov bx,0183H      add ax,bx
      (2)也可以先将低8位相加,再将高8位相加,注意低8位相加会产生进位。
      指令为:mov ax,0198H      mov bx,0183H      add al,bl      adc ah,bh
      例:编写程序将两个128位数据相加,ds:si存放第一个数,ds:di存放第二个数,将结果保存在第一个数的内存空间中。
      采用带进位的加法指令从最低位开始相加,128位是8个字,需循环8次。代码如下:

	sub ax,ax		设置cf位为0
	mov cx,8		设置循环次数为8
  s:mov ax,[si]
	adc ax,[di]
	mov [si],ax
	inc si			inc指令不影响cf位
	inc si
	inc di
	inc di
	loop s			loop指令不影响cf位
带借位减法指令sbb

      指令格式:sbb op1,op2效果为:op1=op1-op2-cf
      示例:计算003E1000H-00202000H的,将结果放在ax,bx中,程序如下:

	mov bx,1000EH		bx中存放高16位
	mov ax,003EH		ax中存放低16位
	sub bx,2000H
	sbb ax,0020H

      adc、sbb都是先对低位做运算,后对高位做运算。

你可能感兴趣的:(汇编语言,汇编语言)