装配中的16位乘法?

所以我使用C和汇编来进行16位有符号乘法.

我知道对于16位,被乘数是AX,乘法器是寄存器或存储器操作数16位,产品存储在EDX:EAX中,它是操作数的两倍.

我是初学者,所以我首先尝试使用8位有符号乘法运算:

#include "stdafx.h"
#include <stdio.h>

int main()
{
    char X, Y;
    short Z;
    _asm
    {
        MOV X, 5
        MOV Y, 11

        MOV AL, X
        MOV BL, Y
        IMUL BL

        MOV Z, AX

    }

    printf("The result times is = %i", Z);



    getchar();
    //system("pause");
    return 0;
}

但我不确定为什么以下代码不适用于16位.

#include "stdafx.h"
#include <stdio.h>

int main()
{
    short X, Y;
    int Z;
    _asm
    {
            MOV X, 5
            MOV Y, 11

            MOV AX, X
            MOV BX, Y
            IMUL BX

            MOV Z, [DX::AX]

    }

    printf("The result times is = %i", Z);



    getchar();
    //system("pause");
    return 0;
}

最佳答案 它不起作用的原因是指令MOV Z,[DX :: AX]不存在.

你是正确的,结果将存储在DX:AX中,但要将这两个寄存器的结果存储在一个内存位置,你必须做两个存储.

lea ecx,z        //load the address of z into cx
mov [ecx],ax     //8086 is little endian, so store the lower bytes first.
mov [ecx+2],dx   //store the high bytes 

我必须说看到16位汇编感到震惊. 386是在1985年推出的,所以你落后了大约30年.

将两个16位值相乘的方法是:

movsx eax, word ptr x        //sign extension prevents partial register writes
movsx edx, word ptr y        //use movzx if you want to do an unsigned mul
imul eax,edx                 //multiply, but only store result in EAX.
mov z,eax                    //save result in one go.

在x86中使用16位寄存器会导致代码速度非常慢,因为处理器未针对此操作模式进行优化.有时16位代码可能比普通代码慢很多倍.
下面的代码运行得比上面快得多.

>它不会因部分寄存器写入而受到停顿的影响.
>它不对部分寄存器执行操作.
>它不使用两次写入(其中一次是未对齐的),其中一次写入就足够了.

您也不必了解上一个示例中little endian的细微之处.
您应该不惜一切代价避免使用16位寄存器.
等效的32位代码几乎总是快得多.
如果您无法将两个16位写入组合到一个32位中,则将16位值写入内存是唯一的例外.

点赞