标题:模拟乘除法指令
取消只看楼主
zwh2698
Rank: 1
等 级:新手上路
帖 子:26
专家分:0
注 册:2005-9-24
 问题点数:0 回复次数:0 
模拟乘除法指令
最近我给一个mcu 写编译器的时候,因为这个mcu 是不支持乘除指令,因此我就写了一个模拟的函数,当然在这里我用的8086 的 asm 描述算法的核心思想,并在vc6.0 编译通过验证。
mulchar()是无符号的8位乘法,mulsignedchar()是有符号的8位乘法,divchar() 是无符号的8位除法。
理论依据:<<计算机组成原理>> 李文兵 清华大学出版社

代码如下:
// testfload.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <math.h>
#include <process.h>
unsigned  mulchar(unsigned char a, unsigned char b);
short mulsignedchar(char a, char b);
unsigned short divchar(unsigned char a, unsigned char b);


int main(int argc, char* argv[])
{
    
    int i =0 ;
    int j = 0;
    int k = 0;

    unsigned short div = divchar(128, 1);
    unsigned char shang = div & 0xff;
    unsigned char rest = (div >> 8) & 0xff;


    // unsigned char
    for (i = 0 ; i <= 255;  i++)
    {
        for (j = 0; j <= 255; j++)
        {
            unsigned short c = (short)i * j;
            unsigned short c1 = mulchar(i, j);
            printf ("%d * %d = %hx, %hx\n", i, j, c, c1);
            if (c != c1)
            {
                k++;
                __asm
                {
                     int 3
                }
            }
        }
    
    }
    system("PAUSE");
    // signed char
    for (i = -128 ; i <= 127;  i++)
    {
        for (j = -128; j <= 127; j++)
        {
            short c = (char)i * j;
            short c1 = mulsignedchar(i, j);
            printf ("%d * %d = %hd, %hd\n", i, j, c, c1);
            if (c != c1)
            {
                k++;
                __asm
                {
                    int 3
                }
            }
        }
        
    }

    for (i = 1; i <= 255; i++)
    {
        for (j = 1; j <= 255; j++)
        {
            unsigned char c = i / j;
            unsigned char s = i % j;
            unsigned short cc = divchar(i, j);
            unsigned char c1 = cc & 0xff;
            unsigned char s1 = (cc >> 8) & 0xff;

            printf("%u / %u = %u---%u=====rest %u----%u\n", i, j, c, c1, s, s1);

            if (c != c1 || s1 != s)
            {
                __asm
                {
                    int 3
                }
            }




        }
    }


    


    printf("errors %d\n", k);
    return 0;
}

short mulsignedchar(char a, char b)
{
     int asign = a & 0x80;
     int bsign = b & 0x80;
     int nsign = asign ^  bsign;
     unsigned char mula = a,  mulb = b;
     if (asign)
     {
         mula = -a;
     }
     if (bsign)
     {
         mulb = -b;
     }
     int result = mulchar(mula, mulb);
     if (nsign)
     {
         result = - result;
     }
     return result;
}

unsigned mulchar(unsigned char a, unsigned char b)
{
    unsigned char aSign = 0;
    unsigned char aSignHigh = 0;
    unsigned char flag = 0;
    unsigned char anSignEx = 0;
    unsigned char anSignExHigh = 0;
    unsigned char a2SignEx = 0;
    unsigned char a2SignExHigh = 0;
    unsigned char tempB = b;
    unsigned char ResultHigh = 0;
    unsigned char ResultHighH = 0;
    unsigned char a2 = 0;
    unsigned char an = 0;
    unsigned short result = 0;


    __asm
    {
            // clear
            mov eax, 0
            mov ebx, 0
            mov ecx, 0
            mov edx, 0
            mov ResultHigh, al
            mov ResultHighH,al
            
            // backup a
            mov al, a
            mov an, al

            
            // extern a sign
            cbw   // don't use because unsigned multiplication
            //cmp XYflag, 0
            //jnz directjmp
            mov ah, 0
;directjmp:
            mov aSign, ah
            mov aSignHigh, ah

            // move 2a sign
            mov a2SignEx, ah
            mov a2SignExHigh, ah
            
            // calculate 2a
            mov Ah, 0
            shl al, 1
            rcl a2SignEx, 1
            rcl a2SignExHigh, 1    
            mov a2, al
        

            // extern an sign
            mov al, a
            xor ah, ah
            mov bx, 0
            sub bx, ax
            mov anSignEx, bh
            mov an, bl
            mov anSignExHigh, bh

            
            // loop count
            mov ch, 0x4
            
            // calculate last 2 bits
            mov bl, b
            and bl, 0x3
            
loopstart:
            cmp flag, 0x0
            jz  directcheck2bit
            // clear flag
            mov flag, 0x0
            inc bl
            cmp bl, 0x3
            jbe directcheck2bit
            // set flag
            mov flag, 1
            and bl, 0x3
directcheck2bit:
            cmp bl, 0x00
            jz labelto00state
            cmp bl, 0x01
            jz labelto01state
            cmp bl, 0x02
            jz labelto02state
            // 03 state
            add dh, an
            mov bh, anSignEx
            adc ResultHigh, bh
            mov bh, anSignExHigh
            adc ResultHighH, bh
            // shift
            SAR ResultHighH, 1
            RCR ResultHigh, 1
            RCR dx, 1
            // shift again
            SAR ResultHighH, 1
            RCR ResultHigh, 1
            RCR dx, 1
            
            // set flag
            mov flag, 0x1
            
            // shift operand b
            mov bl, tempB
            mov cl, 0x2
            SHR bl, cl
            mov tempB, bl
            and bl, 0x3
DecCount:
            dec ch
            jnz loopstart
            jmp result_xy
            
labelto00state:
            // shift
            SAR ResultHighH, 1
            RCR ResultHigh, 1
            RCR dx, 1
            // shift again
            SAR ResultHighH, 1
            RCR ResultHigh, 1
            RCR dx, 1
            // shift operand b
            mov bl, tempB
            mov cl, 0x2
            SHR bl, cl
            mov tempB, bl
            and bl, 0x3
            jmp DecCount
labelto01state:
            add dh, a
            mov bh, aSign
            adc ResultHigh, bh
            adc ResultHighH, bh
            
            // shift
            SAR ResultHighH, 1
            RCR ResultHigh, 1
            RCR dx, 1
            // shift again
            SAR ResultHighH, 1
            RCR ResultHigh, 1
            RCR dx, 1

            // shift
            mov bl, tempB
            mov cl, 0x2
            SHR bl, cl
            mov tempB, bl
            and bl, 0x3
            jmp DecCount
labelto02state:        
            add dh, a2
            mov bh, a2SignEx
            adc ResultHigh, bh
            mov bh, a2SignExHigh
            adc ResultHighH, bh
            
            // shift
            SAR ResultHighH, 1
            RCR ResultHigh, 1
            RCR dx, 1
            // shift again
            SAR ResultHighH, 1
            RCR ResultHigh, 1
            RCR dx, 1


            // shift
            mov bl, tempB
            mov cl, 0x2
            SHR bl, cl
            mov tempB, bl
            and bl, 0x3
            jmp DecCount
result_xy:
            cmp flag, 0
            jz Operandblasttime
            add dh, a
Operandblasttime:
            mov result, dx            
    }    
        return result;    
}

unsigned short divchar(unsigned char a, unsigned char b)
{
    unsigned char result = 0;
    unsigned char rest = 0;
    unsigned char restsign = 0;
    unsigned char bn = 0;
    unsigned char bnsign = 0;
    unsigned char rest2 = 0;
    unsigned char rest2sign = 0;

    __asm
    {
        mov cx, 0
        cmp b, 0
        jnz nextprocess
        int 0  // div exception
nextprocess:
        mov al, a
        cmp al, b
        jb returnresult
        
        // start division
        mov al, a
        mov rest, al
        mov restsign, 0

        // calculate the -b to bn
        mov al, b    
        mov bl, 0
        sub bl, al
        mov al, 0
        sbb al, 0
        mov bnsign, al
        mov bn, bl

        //loop
loopStart:
        mov al, rest
        cmp al, b
        jb  loopexit
        mov al, rest
        sub al, b
        mov rest , al
        mov bl, restsign
        sbb bl, 0
        mov restsign, bl
        inc cl
        //mov bl, restsign
        and bl, 0x80
        jz nonaddY
        mov al, rest
        add al, b
        mov rest, al
        mov bl, restsign
        adc bl, 0
        mov restsign, bl
nonaddY:
        jmp loopStart

returnresult:
        mov al , a
        mov rest, al
loopexit:
        mov result, cl
    }

    unsigned short nR = rest;
    nR <<= 8;
    nR |= result;
    return nR;
}
收到的鲜花
  • 永夜的极光2008-03-01 18:42 送鲜花  8朵   附言:我很赞同
搜索更多相关主题的帖子: 乘除法 指令 清华大学 计算机 mcu 
2008-02-13 18:27



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-199821-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.294281 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved