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. |
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 m32real | Multiply ST(0) by m32real and store result in ST(0) |
FMUL m64real | Multiply 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 |
FMULP | Multiply ST(1) by ST(0), store result in ST(1), and pop the register stack |
FIMUL m32int | Multiply ST(0) by m32int and store result in ST(0) |
FIMUL m16int | Multiply ST(0) by m16int and store result in ST(0) |
List of instructions | https://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. |
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. |
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. |
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. |
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. |
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. |
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. |
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. |
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. |
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; } } |