The Assembler


Push and Pop

You should use pusha to push all general purpose register onto the stack. You should use popa to pop all general purpose register from the stack.
Usted debe usar pusha para hacer push a todos los registros de propósito general hacia el stack. Usted debe usar popa para hacer sacar a todos los registros de propósito general del stack.

Tip
When mixing C++ and ASM code in the same function, you must use: push, pop or pusha and popa, to store the registers as it is shown in the following codes.
Cuando usted mezcla C++ y código ASM en la misma función, usted debe usar: push, pop, pusha y popa para almacenar los registros como se muestra en los siguientes códigos.

Tip
The following code shows how to use the integer and float stacks.
El código de abajo muestra cómo usar los stacks para enteros y valores de punto flotante.

Program.cpp
void Program::MyFunc()
{
     __asm
     {
          //___________________ Push 0 into the int stack
          push          0
          //___________________ Push 0.0 into the float stack: st(0) = 0.0
          fldz
          //___________________ Pop st(0) from the stack to z
          fstp qword ptr [z]
     }
}


Tip
The following code shows how to pass an integer value from C++ code to ASM code.
El código de abajo muestra cómo pasar un valor entero desde código de C++ a código ASM.

Program.cpp
void Program::btCalculate_Click(Win::Event& e)
{
     //___________________ Passing an int value
     int x = 10;
     __asm
     {
          push          edx;
          mov          edx, dword ptr[x]; // edx = x; In this case x is the memory address, and [x] is the value in the memory address
          pop          edx;
     }
}


Tip
The following code shows how to return an integer value from ASM code to C++ code.
El código de abajo muestra cómo regresar un valor entero desde código ASM a código en C++.

Program.cpp
void Program::MyFunc()
{
     //___________________ Returning an int value
     int x = 8;
     __asm
     {
          push          edx;
          mov          edx, 00Ah;
          mov          dword ptr[x], edx;
          pop          edx;
     }
}


Tip
The following code shows how to pass a double value from C++ code to ASM code.
El código de abajo muestra cómo pasar un valor double desde código de C++ a código ASM.

Program.cpp
void Program::MyFunc()
{
     //___________________ Passing a double value
     double x = 10.0;
     __asm
     {
          fld          qword ptr[x];      // Push the double value in to the float stack
          ...
     }
}


Tip
The following code shows how to return a double value from ASM code to C++ code.
El código de abajo muestra cómo regresar un valor double desde código ASM a código en C++.

Program.cpp
void Program::MyFunc()
{
     //___________________ Returning a double value
     double x = 10.0; // returned value is stored here
     __asm
     {
          ...
          fstp          qword ptr[x]; // Pop a value from the stack into x
     }
}


Problem 1
Create a Wintempla Dialog application called Program to test how to multiply two double values in ASM using fmul. This program does not run, when it is compiled using 64 bits.
Cree una aplicación de Diálogo de Wintempla llamada Program para probar cómo multiplicar dos valores double en ASM usando fmul. Este programa no corre, cuando se compila a 64 bits.

MulGUI

MulRun

Program.cpp
void Program::Window_Open(Win::Event& e)
{
}

void Program::btCalculate_Click(Win::Event& e)
{
     //___________________ Double multiply with fmul
     double x = tbxX.DoubleValue;
     double y = tbxY.DoubleValue;
     double z = 0.0;
     // z = x*y;
     __asm
     {
          fld          qword ptr[x]; // Push x in to the float stack
          fmul          qword ptr[y]; // Multiply the top of the stack by y, result is at the top of the stack
          fstp          qword ptr[z]; // Pop the top from the stack into z
     }
     tbxOutput.DoubleValue = z;
}


Instruction    Description  
FMUL m32realMultiply ST(0) by m32real and store result in ST(0)
FMUL m64realMultiply ST(0) by m64real and store result in ST(0)
FMUL ST(0), ST(i)Multiply ST(0) by ST(i) and store result in ST(0)
FMUL ST(i), ST(0)Multiply ST(i) by ST(0) and store result in ST(i)
FMULP ST(i), ST(0)Multiply ST(i) by ST(0), store result in ST(i), and pop the register stack
FMULPMultiply ST(1) by ST(0), store result in ST(1), and pop the register stack
FIMUL m32intMultiply ST(0) by m32int and store result in ST(0)
FIMUL m16intMultiply ST(0) by m16int and store result in ST(0)
List of instructionshttps://digitalmars.com/ctg/ctgInlineAsm.html

Floating Point Stack (ST)

The floating point stack, ST, has eight memory locations: ST(0), ST(1), ... ST(7). ST(1) means one position below the top of the stack, ST(2) means two positions below the top of the stack, etc. Therefore, a push moves ST(0) to ST(1), ST(1) to ST(2), etc. Similarly, a pop moves ST(1) to ST(0), ST(2) to ST(1), etc. Pushing a full stack or popping an empty stack is a run time error.
El stack de punto flotante, ST, tiene ocho ubicaciones de memoria ST(0), ST(1), ... ST(7). ST(1) quiere decir una posición por debajo de la parte superior del stack, ST(2) quiere decir dos posiciones debajo de la parte superior del stack, etc. Por lo tanto, un push mueve ST(0) a ST(1), ST(1) a ST(2),etc. De forma similar, un pop mueve ST(1) a ST(0), ST(2)a ST(1), etc. Haciendo un push en stack lleno o haciendo un pop en un stack vacío generará un error en el momento de ejecución.

Problem 2
Modify the code of the previous problem to test how to multiply two double values in ASM using mulp.
Modifique el código del problema previo para probar cómo multiplicar dos valores double en ASM usando mulp.

MulpRun

Program.cpp
...

void Program::btCalculate_Click(Win::Event& e)
{
     //___________________ Double multiply with fmulp
     double x = tbxX.DoubleValue;
     double y = tbxY.DoubleValue;
     double z = 0.0;
     // z = x*y;
     __asm
     {
          fld          qword ptr[x];// Push x in to the float stack
          fld          qword ptr[y];// Push y in to the float stack
          fmulp          st(1), st(0);// Result is at the top of the stack, one value is pop
          fstp          qword ptr[z];// Pop the top value from the stack into z

     }
     tbxOutput.DoubleValue = z;
}


Problem 3
Modify the code of the previous problem to test how to add two integer values in ASM.
Modifique el código del problema previo para probar cómo sumar dos valores enteros en ASM.

IntAddRun

Program.cpp
...
void Program::btCalculate_Click(Win::Event& e)
{
     //___________________ int Add
     int x = tbxX.IntValue;
     int y = tbxY.IntValue;
     int z = 0;
     //z = x + y;
     __asm
     {
          push          edx;
          push          eax;
          ;
          mov          edx, dword ptr[x];
          mov          eax, dword ptr[y];
          add          eax, edx;
          mov          dword ptr[z], eax;
          ;
          pop          eax;
          pop          edx;
     }
     tbxOutput.IntValue = z;
}


Problem 4
Modify the code of the previous problem to test how to add two double values in ASM.
Modifique el código del problema previo para probar cómo sumar dos valores double en ASM.

DoubleAddRun

Program.cpp
...
void Program::btCalculate_Click(Win::Event& e)
{
     //___________________ double Add
     double x = tbxX.DoubleValue;
     double y = tbxY.DoubleValue;
     double z = 0.0;
     // z = x+y;
     __asm
     {
          fld          qword ptr[x];
          fadd          qword ptr[y];
          fstp          qword ptr[z];
     }
     tbxOutput.DoubleValue = z;
}


Problem 5
Modify the code of the previous problem to test how to add two double values in an array in ASM.
Modifique el código del problema previo para probar cómo sumar dos valores double en un arreglo en ASM.

ArrayAddRun

Program.cpp
...
void Program::btCalculate_Click(Win::Event& e)
{
     //___________________ double array Add with two elements
     double x[2];
     x[0] = tbxX.DoubleValue;
     x[1] = tbxY.DoubleValue;

     double sum = 0.0;
     __asm
     {
          fld          qword ptr[sum]; // st(0) = sum;
          fadd          qword ptr[x]; // st(0) += x[0];
          fadd          qword ptr[x + 8]; // st(0) += x[1];
          fstp          qword ptr[sum]; // sum = st(0);
     }
     tbxOutput.DoubleValue = sum;
}


Problem 6
Modify the code of the previous problem to test how to add double values in an array in ASM using a loop.
Modifique el código del problema previo para probar cómo sumar valores double en un arreglo en ASM usando un loop.

DoubleArrayLoopRun

Program.cpp
...
void Program::btCalculate_Click(Win::Event& e)
{
     //___________________ double array Add with LOOP
     double x[3];
     x[0] = tbxX.DoubleValue;
     x[1] = tbxY.DoubleValue;
     x[2] = 10.0;
     int len = 3;
     double sum = 0.0;
     __asm
     {
          push          ecx;
          push          edx;
          ;
          mov          ecx, dword ptr[len]; // ecx = len;
          mov          edx, 0; // edx = 0;
          fldz; // st(0) = 0.0;
     SUMAX:
          fadd          qword ptr[x + edx];      // st(0) += x[0];
          add          edx, 8; // edx += 8;
          loop          SUMAX;
          fstp          qword ptr[sum]; // sum = st(0);
          ;
          pop          edx;
          pop          ecx;
     }
     tbxOutput.DoubleValue = sum;
}


Problem 7
Modify the code of the previous problem to test how to add the values in an STL valarray in ASM.
Modifique el código del problema previo para probar cómo sumar valores de un valarray de la STL en ASM.

ValarrayAddRun

Program.cpp
...
void Program::btCalculate_Click(Win::Event& e)
{
     //___________________ valarray Add with LOOP
     valarray<double> x;
     Sys::Convert::ToVector(tbxX.Text, x);
     int len = (int)x.size();
     double * p = &x[0];
     double z = p[0];
     double sum = 0.0;
     __asm
     {
          push          eax;
          push          ecx;
          push          edx;
          ;
          mov          eax, dword ptr[p]; // eax = p
          mov          ecx, dword ptr[len]; // ecx = len;
          mov          edx, 0; // edx = 0;
          fldz; // st(0) = 0.0;
     SUMAX:
          fadd          qword ptr[eax + edx]; // st(0) += x[edx/8];
          add          edx, 8; // edx += 8;
          loop          SUMAX;
          fstp          qword ptr[sum]; // sum = st(0);
          ;
          pop          edx;
          pop          ecx;
          pop          eax;
     }
     tbxOutput.DoubleValue = sum;
}


Problem 8
Modify the code of the previous problem to test how to add double values in a valarray in ASM using JNZ.
Modifique el código del problema previo para probar cómo sumar valores double en un valarray en ASM usando JNZ.

JnzRun

Program.cpp
..
void Program::btCalculate_Click(Win::Event& e)
{
     //___________________ double array Add with JNZ
     valarray<double> x;
     Sys::Convert::ToVector(tbxX.Text, x);
     int len = (int)x.size();
     double * p = &x[0];
     double sum = 0.0;
     __asm
     {
          push          eax;
          push          ecx;
          push          edx;
          ;
          mov          eax, dword ptr[p]; // eax = p
          mov          ecx, dword ptr[len]; // ecx = len;
          mov          edx, 0; // edx = 0;
          fldz; // st(0) = 0.0;
     SUMAX:
          fadd          qword ptr[eax + edx]; // st(0) += x[edx/8];
          add          edx, 8; // edx += 8;
          dec          ecx; // ecx--;
          jnz          SUMAX; // if (ecx != 0) jump to SUMAX
          fstp          qword ptr[sum]; // sum = st(0);
          ;
          pop          edx;
          pop          ecx;
          pop          eax;
     }
     tbxOutput.DoubleValue = sum;
}


Program.cpp
// This code uses an array of double values instead of a valarray
void Program::MyFunc()
{
     //___________________ double array Add with JNZ
     double x[3];
     x[0] = -5.5;
     x[1] = 11.3;
     x[2] = 16.2;
     int len = 3;
     double sum;
     __asm
     {
          push          ecx;
          push          edx;
          ;
          mov          ecx, dword ptr[len];// ecx = len;
          mov          edx, 0;// edx = 0;
          fldz; // st(0) = 0.0;
     SUMAX:
          fadd          qword ptr[x + edx];// st(0) += x[0];
          add          edx, 8;// edx += 8;
          dec          ecx;// ecx--;
          jnz          SUMAX;// if (ecx != 0) jump to SUMAX
          fstp          qword ptr[sum];// sum = st(0);
          ;
          pop          edx;
          pop          ecx;
     }
}


Problem 9
Modify the code of the previous problem to test how to divide by two an integer value.
Modifique el código del problema previo para probar cómo dividir entre dos un valor entero.

DivideByTwoRun

Program.cpp
...
void Program::btCalculate_Click(Win::Event& e)
{
     //___________________ Divide by two
     int x = tbxX.IntValue;
     int result;
     __asm
     {
          push          ecx;
          ;
          mov          ecx, dword ptr[x]; // ecx = x;
          shr          ecx, 1; // shift right: ecx /= 2;
          mov          dword ptr[result], ecx;      // result = ecx;
          ;
          pop          ecx;
     }
     tbxOutput.IntValue = result;
}


Problem 10
Modify the code of the previous problem to test how to compute the module (percent operator in C++) of two integer values.
Modifique el código del problema previo para probar cómo calcular el módulo (el operador de porcentaje en C++) de dos valores enteros.

ModuleRun

Program.cpp
...
void Program::btCalculate_Click(Win::Event& e)
{
     //___________________ Module result = x%y
     int x = tbxX.IntValue;
     int y = tbxY.IntValue;
     int result = 0;
     __asm
     {
          mov          eax, dword ptr[x]; // eax = x;
          cdq;          // Convert double-word to quad-word: sign-extends EAX into EDX
          idiv          dword ptr[y]; // DX:AX = DX:AX / r/m; resulting EDX = remainder
          mov          dword ptr[result], edx; // result = edx;
     }
     tbxOutput.IntValue = result;
}


Tip
The following code shows how to move text between ASM and C++.
El código de abajo muestra cómo mover texto entre ASM y C++.

Program.cpp
void Program::MyFunc()
{
     char format[] = "%s %s\n";
     char hello[] = "Hello";
     char world[] = "world";

     __asm
     {
          mov eax, offset world;
          push eax;
          mov eax, offset hello;
          push eax;
          mov eax, offset format;
          push eax;
     }
}


© Copyright 2000-2021 Wintempla selo. All Rights Reserved. Jul 22 2021. Home