从高级语言到汇编2

作者:潇潇  出处:www.j2mefans.com
该文章为本站原创,如有引用,请注明出处和作者


第二篇    算术运算

对于高级语言除了赋值操作外,还包括算术运算加(+)、减(-)、乘(*)、除(/)、求余(或称模运算,%),下面是一个简单的例子:
int main(int argc, char* argv[])
{
    int a,b,c;
    

    a=1;
    b=2;
    c=a+b;
    printf("%d/n",c);  /*  3 */

    c=b-a;
    printf("%d/n",c);  /*  1 */

    c=b*a;
    printf("%d/n",c);   /*  2 */

c=b/a;
    printf("%d/n",c);   /*  2 */
    
c=b%a;
    printf("%d/n",c);   /*  0 */

    return 0;
}

我们看看他的汇编程序的样子:


c=a+b;      
0040D716   mov         eax,dword ptr [ebp-4]   ;将a移动到eax
0040D719   add         eax,dword ptr [ebp-8]     ;将eax中的值加上b,将结果放到eax中
0040D71C   mov         dword ptr [ebp-0Ch],eax  ;将eax中的结果,移动到c

c=b-a;
0040D730   mov         edx,dword ptr [ebp-8]     ;将b移动到eax
0040D733   sub         edx,dword ptr [ebp-4]   ;将eax中的值减去a,将结果放到eax中
0040D736   mov         dword ptr [ebp-0Ch],edx  ;将eax中的结果,移动到c

c=b*a;
0040D74A   mov         ecx,dword ptr [ebp-8]  ;将b移动到eax
0040D74D   imul        ecx,dword ptr [ebp-4]   ;将eax中的值乘以a,将结果放到eax中
0040D751   mov         dword ptr [ebp-0Ch],ecx   ;将eax中的结果,移动到c

c=b/a;
0040D780   mov         eax,dword ptr [ebp-8]  ;将b移动到eax
0040D783   cdq
0040D784   idiv        eax,dword ptr [ebp-4]   ; ;将eax中的值除以a,将结果放到eax中
0040D787   mov         dword ptr [ebp-0Ch],eax    ;将eax中的结果,移动到c

c=b%a;
0040D765   mov         eax,dword ptr [ebp-8]   ;将b移动到eax
0040D768   cdq
0040D769   idiv        eax,dword ptr [ebp-4]     ;将eax中的值除以a,将结果放到eax中
0040D76C   mov         dword ptr [ebp-0Ch],edx    ;将eax中的结果,移动到c

那么也就是说,在汇编语言中,使用add指令作为加运算,使用sub指令作为减运算,imul指令作为乘运算,idiv作为除运算。

深入一:

对于汇编语言的算术运算指令系统,要比高级语言的复杂一些。往往实现一种功能的指令因为有符号数和无符号数等编码的不同以及进位借位的关系会有许多个不同的指令。
比如加法运算指令:在80x86中就有四种:加法指令ADD(ADD Binary Numbers Instruction),带进位加指令ADC(ADD With Carry Instruction),加1指令INC(Increment by 1 Instruction)以及交换加指令XADD(Exchange and Add)。
我们再此仅对出现的加以分析(包括其他的算术运算系统)。
1、加法指令ADD(ADD Binary Numbers Instruction)。 指令的功能是把源操作数的值加到目的操作数中。
受影响的标志位:AF、CF、OF、PF、SF和ZF
2、减法指令SUB(Subtract Binary Values Instruction)
指令的功能是从目的操作数中减去源操作数。
受影响的标志位:AF、CF、OF、PF、SF和ZF

3、有符号数乘法指令IMUL(Signed Integer Multiply Instruction)
乘法指令的被乘数都是隐含操作数,乘数在指令中显式地写出来。CPU会根据乘数是8位、16位,还是32位操作数,来自动选用被乘数:AL、AX或EAX。
指令的功能是把显式操作数和隐含操作数相乘,并把乘积存入相应的寄存器中。
受影响的标志位:CF和OF(AF、PF、SF和ZF无定义)
4、有符号数除法指令IDIV(Signed Integer Divide Instruction)
除法指令的被除数是隐含操作数,除数在指令中显式地写出来。CPU会根据除数是8位、16位,还是32位,来自动选用被除数AX、DX-AX,还是EDX-EAX。
除法指令功能是用显式操作数去除隐含操作数,可得到商和余数。当除数为0,或商超出数据类型所能表示的范围时,系统会自动产生0号中断。
受影响的标志位:AF、CF、OF、PF、SF和ZF

深入二:有符号数与无符号数
计算机的许多指令分为无符号乘法指令和有符号的指令,他们分别用来处理有符号数和无符号数,这也增加了汇编语言指令系统的复杂性,在学习的时候要看清楚。有符号数和无符号数的唯一区别就在于:数据的最高位是作为“数值”参与运算,还是作为“符号位”参与运算。
对于有符号数我们知道他表示的范围是从一个负数到一个整数,所以就需要将最高位座位符号位来处理。而无符号数表示的范围是0到整数,就可以将所有的位数作为数值参与运算。
例如我们知道的高级语言的int类型,表示的范围从-32767到+32767。相应的无符号unsigned int       表示的数值范围是      0~65535

深入三:标志位
16位CPU内部有一个16位的标志寄存器,它包含9个标志位。这些标志位主要用来反映处理器的状态和运算结果的某些特征。
有些指令的执行会改变标志位(如:算术运算指令等),不同的指令会影响不同的标志位,有些指令的执行不改变任何标志位(如:MOV指令等),有些指令的执行会受标志位的影响(如:条件转移指令等),也有指令的执行不受其影响。
程序员要想熟练运用这些标志位,就必须掌握每个标志位的含义、每条指令的执行条件和执行结果对标志位的作用。
1、进位标志CF(Carry Flag)
进位标志CF主要用来反映运算是否产生进位或借位。如果运算结果的最高位产生了一个进位或借位,那么,其值为1,否则其值为0。
使用该标志位的情况有:多字(字节)数的加减运算,无符号数的大小比较运算,移位操作,字(字节)之间移位,专门改变CF值的指令等。
2、零标志ZF(Zero Flag)
零标志ZF用来反映运算结果是否为0。如果运算结果为0,则其值为1,否则其值为0。在判断运算结果是否为0时,可使用此标志位。

3、符号标志SF(Sign Flag)
符号标志SF用来反映运算结果的符号位,它与运算结果的最高位相同。在微机系统中,有符号数采用补码表示法,所以,SF也就反映运算结果的正负号。运算结果为正数时,SF的值为0,否则其值为1。
4、溢出标志OF(Overflow Flag)
溢出标志OF用于反映有符号数加减运算所得结果是否溢出。如果运算结果超过当前运算位数所能表示的范围,则称为溢出,OF的值被置为1,否则,OF的值被清为0。
5、辅助进位标志AF(Auxiliary Carry Flag)
在发生下列情况时,辅助进位标志AF的值被置为1,否则其值为0:
(1)、在字操作时,发生低字节向高字节进位或借位时;
(2)、在字节操作时,发生低4位向高4位进位或借位时。
对以上6个运算结果标志位,在一般编程情况下,标志位CF、ZF、SF和OF的使用频率较高,而标志位PF和AF的使用频率较低
6、奇偶标志PF(Parity Flag)
奇偶标志PF用于反映运算结果中“1”的个数的奇偶性。如果“1”的个数为偶数,则PF的值为1,否则其值为0。
利用PF可进行奇偶校验检查,或产生奇偶校验位。在数据传送过程中,为了提供传送的可靠性,如果采用奇偶校验的方法,就可使用该标志位。
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值