zwh2698 发表于 2008-2-13 18:27

模拟乘除法指令

最近我给一个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-3-1 11:45

学习下子啦.

页: [1]

编程论坛