为功能创建宏

时间:2013-11-19 19:07:28

标签: assembly x86

我想知道为什么每当我尝试进行分割步骤时,我的宏总是会说尝试除以0。我不知道我做错了什么,宏看起来很简单,我是否在我的除法宏上陷入困境?

到目前为止,这是我的代码

.386

.model flat

 StartDiv macro
    push ebp
    mov ebp, esp
    sub esp, 8
    mov eax, [ebp + NumA]
    mov ebx, [ebp + NumB]
endm

Divide macro
    cdq
    idiv ebx
endm

FinishDiv macro
    mov [ebp - 4], eax
    add esp, 8
    pop ebp
endm

StartMul macro
    push ebp
    mov ebp, esp
    sub esp, 8
    mov eax, [ebp + NumA]
    mov ecx, [ebp + NumB]
endm

Multiply macro
    imul ecx
endm

FinishMul macro
    mov [ebp - 4], eax
    add esp, 8
    pop ebp
    ret
endm

StartSq macro
    mov eax, [esp+4]
endm

Square macro
    imul eax
endm

FinishSq macro
    ret
endm

.code

extrn           _PrintResult:proc
NumA            = 8
NumB            = 12
Remainder       = 16

_Divide proc
    StartDiv
    Divide
    FinishDiv
_Divide endp

_Multiply proc
    StartMul
    Multiply
    FinishMul
_Multiply endp

_Square proc
    StartSq
    Square
    FinishSq
_Square endp

end

这是主要代码:     #include

using namespace std;

enum ResultCode     {ShowSquare, ShowMultiply, ShowDivide, ShowRemainder,       ShowDivideFailure};
enum SuccessCode    {Failure, Success};

extern "C" SuccessCode Divide (long, long, long &, long &);
extern "C" long Multiply (long, long);
extern "C" void PrintResult (ResultCode, long);
extern "C" long Square (long);

void main ()
{
long Num1; 
long Num2;
long Result;
long Remainder;
do
    {
    cout << "Enter Number to Square" << endl;
    cin >> Num1;
    Result = Square (Num1);
    cout << "Square is: " << Result << endl;
    cout << "Enter two numbers to multiply" << endl;
    cin >> Num1 >> Num2;
    Result = Multiply (Num1, Num2);
    cout << "Result of multiply is: " << Result << endl;
    cout << "Enter mumber to divide into then number to divide by" << endl;
    cin >> Num1 >> Num2;
    if (Divide (Num1, Num2, Result, Remainder) == Success)
            cout << "Result is " << Result << " and remainder is " <<    Remainder << endl;
        else
            cout << "Attempted division by zero";
    } while (Result > 0);
}

void PrintResult (ResultCode PrintCode, long Value)
{
switch (PrintCode)
    {
    case ShowSquare:
            cout << "Display of square is: " << Value << endl;
            break;
    case ShowMultiply:
            cout << "Display of multiply is: " << Value << endl;
            break;
    case ShowDivide:
            cout << "Display of divide is " << Value << endl;
            break;
    case ShowRemainder:
            cout << "Display of remainder is " << Value << endl;
            break;
    case ShowDivideFailure:
            cout << "Display of Division by zero" << endl;
            break;
    default:
            cout << "Error in assembly routines" << endl;
    }
}

1 个答案:

答案 0 :(得分:0)

您可以使用内联汇编解决问题 - 然后您就可以调试内容了。您可以使用所谓的函数来告诉c / c ++编译器让我对我的代码负全部责任(编译器根本不会干涉 - 没有前导码,没有留下代码,没有回报 - 一切都取决于你。

以下是您的部门内容的样子:

__declspec(naked) int my_div(int num1, int num2, int *result, int *reminder)
{
    _asm{
        push ebp
        mov ebp, esp

        //sub esp, 8  // for 2 local int(32bit) variables - but you do not have any

        //mov dword ptr[ebp-4], 3   // set one local var to 3
        //mov dword ptr[ebp-8], 4   // set one local var to 4

        mov eax, dword ptr [ebp+8]   // dividend
        cdq                          //   sign extend EAX's content to EDX:EAX
        mov ebx, dword ptr [ebp+12]  // divisor  
        idiv ebx                     //   divide EDX:EAX by EBX and put result in EAX and reminder in EDX
        mov ecx, dword ptr [ebp+16]  // pointer to result
        mov dword ptr [ecx], eax     //   write result back
        mov ecx, dword ptr [ebp+20]  // pointer to reminder
        mov dword ptr [ecx], edx     //   write reminder back

        // return value must be in EAX - but it is up to you now
        //add esp, 8 // remove space for local vars

        mov esp, ebp
        pop ebp
        ret
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    int dividend = 63;
    int divisor = 6;
    int result = 0;
    int reminder = 0;

    my_div(dividend, divisor, &result, &reminder);
    printf("%d/%d = %d rem %d\n", dividend, divisor, result, reminder );

    getchar();
    return 0;
}

结果:

63/6 = 10 rem 3

以下是一些提示&amp;我的意见:

首先 - 不要在这里使用宏 - 用于重复代码。

第二 - 这是你的div代码:

push ebp
mov ebp, esp
sub esp, 8
mov eax, [ebp + NumA]
mov ebx, [ebp + NumB]

cdq
idiv ebx

mov [ebp - 4], eax
add esp, 8
pop ebp

这里几乎没有问题:

  • sub esp,8并添加esp,8 - 无用 - 你不需要空间用于局部变量,因为你不使用它们
  • NumA和NumB定义如下,因此可能无效(无法检查,请自行检查)
  • 您必须阅读 cdecl 调用约定,因为您不知道如何使用它(old new thing calling convwiki
  • 返回值应该在EAX寄存器中(您的成功,失败的值) - 在我跳过它时自己添加适当的代码

此代码的下一堆问题:

if (Divide (Num1, Num2, Result, Remainder) == Success)
  • 正如我所说,你的成功价值必须通过EAX
  • 返回
  • 结果和提醒必须通过,但不是这样 - 你需要它来传递指针 - 就像在我的例子中,在div例程中你使用这些指针来写结果和提醒回来

一般来说,上述所有内容都适用于其余代码。

希望这有助于编码。