I am a little confused as to what I need to fix to handle the error Exception thrown at 0x00AFF748 in ProjectTwo.exe: 0xC0000005: Access violation executing location 0x00AFF748.
I am attempting to write an external assembly language program that is then called by a C++ program. I am unsure if I messed up the assembly language code and that is why I keep getting the error. The goal of my program is
int problem1_ ( )
{
int numberArray [4] = {1, -3, 12, 15};
int result = 0, index = 0;
int numElements = 4;
while (index < numElements)
{
if ( index >= 1 && numberArray[index] > 2 )
{
result = result * numberArray[index] ;
}
else
{
result = result - 5;
}
index++;
}
return result;
}
My C++ Code:
#include<iostream>
using namespace std;
extern "C" int problem1_();
int main()
{
//Declare the variable and set it to returned result
//From calling the assembly program
int x = problem1_();
//Print the results
cout << "The result is: "<< x << endl;
return 0;
}
My assembly Language code:
.model flat, c
.data
numberArray DWORD 1, -3, 12, 15
numElements DWORD 5
.code
problem1_ proc
mov eax, 0 ;value of eax is 0
lea ebx, numberArray ;Load the array's memory address into register ebx'
mov ecx, numElements ;ecx is count down counter
cmp ecx, 0 ;If ecx not greater than 0, jump to quit
jng FINISH
iterateThruArray:
cmp[ebx], eax ;Compare value at current index to eax
jl result1
jmp result2
result1:
mul numberArray
jmp FINISH
result2:
sub eax, 5
jmp FINISH
FINISH:
pop ebp ; pop ebp from the stack
ret ; return to calling program
problem1_ endp
end
Related
I create this piece of code in VS (C++)
#include<iostream>
using namespace std;
static short arr[10];
void powers() {
_asm {
mov ecx, 0;
mov dx, 0;
for:
mov ax, cx;
inc ax;
mul ax;
mov[arr + 2 * ecx], ax;
inc ecx;
cmp ecx, 10;
jl for;
}
}
Now I want to create another function which prints "Pow (x) = x^2", I stuck here:
void print_power(unsigned short x) {
const char* f = "Pow(%d) = %d \n";
_asm {
call powers
push f
add esp, 4
}
}
When I call my "powers" function from "print_power" -> my arr[10] gets filled with the ^2 of 1 to 10
(arr[0] = 1, arr[1] = 4, arr[2] = 9, arr[3] = 16, arr[4] = 25 .....) (I think)
I want when I call my print_power(x) function from main(), for example print_power(8) -> to print the 8th element from my arr like this: "Pow (8) = 81".
Thank you in advance, also I want to apologize if I have some mistakes.
To give you context over the code, this is a dot product computation of two vectors using pointer arithmetic (looping with pointers as well). I have linked it in my main.cpp but for some reason, when the function is called (in this case, my ASM file), i get an access violation error. Here are the two files. Thank you for your help!
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <algorithm>
#include <iostream>
using namespace std;
extern "C" int dpp_pointerr(int *v, int *u, int n); //ASM FILE
void main(void) {
const int N = 10;
static int A[10];
static int B[10];
printf("Array A: ");
for (int i = 0; i < N; i++) { A[i] = rand() % 10; /*printf("%d ", A[i]); */ }
printf("\n\nArray B: ");
for (int j = 0; j < N; j++) { B[j] = rand() % 10;/* printf("%d ", B[j]);*/ }
printf("\n");
int result2 = dpp_pointerr(A, B, N);
printf("\nResult after POINTER dot product: %d\n", result2);
__int64 ctr1 = 0, ctr2 = 0, freq = 0;
int acc = 0, i = 0;
if (QueryPerformanceCounter((LARGE_INTEGER *)&ctr1) != 0) {
/****************CODE TO BE TIMED HERE**********************/
//int result3= dot_product_index(A, B, N);
int result2 = dpp_pointerr(A, B, N);
/**********************************************************/
QueryPerformanceCounter((LARGE_INTEGER *)&ctr2);
cout << "Start Value: " << ctr1 << endl;
cout << "End Value: " << ctr2 << endl;
QueryPerformanceFrequency((LARGE_INTEGER *)&freq);
// freq is number of counts per second. It approximates the CPU frequency
printf("QueryPerformanceCounter minimum resolution: 1/%I64u Seconds.\n", freq);
printf("ctr2 - ctr1: %f counts.\n", ((ctr2 - ctr1) * 1.0 / 1.0));
cout << "65536 Increments by 1 computation time: " << ((ctr2 - ctr1) * 1.0 / freq) << " seconds\n";
}
else {
DWORD dwError = GetLastError();
printf("Error value = %d", dwError);
}
cout << endl;
cout << "Press ENTER to finish";
system("pause");
}
ASM FILE
; Listing generated by Microsoft (R) Optimizing Compiler Version 19.11.25547.0
TITLE C:\Users\Patrick\source\repos\dot_product_legit\dot_product_legit\dpp_pointerr.cpp
.686P
.XMM
include listing.inc
.model flat, C
PUBLIC dpp_pointerr
_TEXT SEGMENT
_result$ = -32 ; size = 4
_B_beg$ = -20 ; size = 4
_A_beg$ = -8 ; size = 4
_v$ = 8 ; size = 4
_u$ = 12 ; size = 4
_n$ = 16 ; size = 4
?dpp_pointerr##YAHPAH0H#Z:
dpp_pointerr PROC ; dot_product_pointer, COMDAT
push ebp
mov ebp, esp
sub esp, 228 ; 000000e4H
push ebx
push esi
push edi
lea edi, DWORD PTR [ebp-228]
mov ecx, 57 ; 00000039H
mov eax, -858993460 ; ccccccccH
rep stosd
mov DWORD PTR _result$[ebp], 0
; Line 11
; Line 2
push ebp
mov ebp, esp
sub esp, 228 ; 000000e4H
push ebx
push esi
push edi
lea edi, DWORD PTR [ebp-228]
mov ecx, 57 ; 00000039H
mov eax, -858993460 ; ccccccccH
rep stosd
; Line 5
mov eax, 4
imul ecx, eax, 0
add ecx, DWORD PTR _v$[ebp]
mov DWORD PTR _A_beg$[ebp], ecx
; Line 6
mov eax, 4
imul ecx, eax, 0
add ecx, DWORD PTR _u$[ebp]
mov DWORD PTR _B_beg$[ebp], ecx
; Line 8
mov DWORD PTR _result$[ebp], 0
; Line 11
mov eax, DWORD PTR _A_beg$[ebp]
mov ebx, DWORD PTR _B_beg$[ebp]
mov ecx, DWORD PTR _n$[ebp]
mov edi, DWORD PTR _v$[ebp]
lea edi, DWORD PTR [edi+ecx*4]
mov esi, DWORD PTR _u$[ebp]
lea esi, DWORD PTR [esi+ecx*4]
jmp SHORT $LN4#dot_produc
$LN2#dot_produc:
add eax, 4
add ebx, 4
$LN4#dot_produc:
cmp eax, edi
jae SHORT $LN3#dot_produc
cmp ebx, esi
jae SHORT $LN3#dot_produc
; Line 12
imul eax, ebx
add DWORD PTR _result$[ebp], eax
jmp SHORT $LN2#dot_produc
$LN3#dot_produc:
; Line 13
mov eax, DWORD PTR _result$[ebp]
; Line 14
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret 0
dpp_pointerr ENDP ; dot_product_pointer
_TEXT ENDS
END
Im trying to check the even numbers from an array inside a struct, but i dont think i wrote something right. When debugging, (i.e. count = 3 v[] = {1,2,4}), after it reaches " cmp eax,[ebp+12] and je outt; " , it goes to outt: and thats it.
s is supposed to keep the sum of all even numbers, eax inside int suma(test *) is index for array, and edx keeps the sum before moving it in s
what am i doing wrong?
#include "stdafx.h"
#include <iostream>
using namespace std;
struct test {
int v[10];
short count;
};
test a;
int s = 6;
int suma(test *)
{
_asm {
mov eax, 0; // i for counting inside array
mov edx, 0; // sum of even elements
mov ebx, [ebp + 8]; // array v adress
loop:
cmp eax, [ebp + 12];
je outt;
mov ecx, [ebx + 4 * eax];
inc eax;
mov edi, ecx
and ecx, 1;
cmp ecx, 1;
je loop;
add edx, edi;
jmp loop;
outt:
mov eax, edx;
}
return s;
}
int main()
{
cin >> a.count;
for (int i = 0; i < a.count; i++)
cin >> a.v[i];
_asm {
LEA eax, a
push eax;
call suma;
add esp, 4;
mov s, eax;
}
cout << s;
return 0;
}
I am really struggling to get my head around this task which I've been given and I'm going out of my mind right now.
I have been given an example of the following loop:
#include <iostream> // for cout
using namespace std;
//declare an array of 'marks'.
const int array_size = 5;
int marks [] = {45,56,99,19,21};
int main()
{int index, average, total;
total = 0;
for ( index = 0; index < array_size; index++)
{
total = total + marks [index];
}
average = total/array_size;
cout << "\nAverage value = " << average << "\n\n";
return(0);
}
in assembly:
#include <iostream> // for cout
using namespace std;
const int array_size = 5;
int marks [] = {45,56,99,19,21}; //declare an array of 'marks'.
int main()
{int index, average, total;
__asm {
mov total,0 ;total = 0;
; ************************** This part is the FOR loop *************************
mov index,0 ;for ( index = 0; index < array_size; index++)
jmp checkend
forloop1:
mov eax,index ;add 1 to index
add eax,1
mov index,eax
checkend:
cmp index,5 ;check if 5 ('array_size') loops have been done
jge endfor1 ;jump if greater than or equal to (remember?)
mov ecx,index
mov edx,total ; total =
add edx,[ecx*4+marks] ; total + marks [index];
mov total,edx
jmp forloop1
; ******************************************************************************
endfor1:
mov eax,total ;average = total/array_size;
cdq ;convert EAX to quadword (uses EDX register)
mov ecx,5 ;get array_size as divisor
idiv ecx ;divides EDX:EAX pair by ECX, EAX=answer
mov average,eax ;save answer in variable 'average'
} //end of assembly section
cout << "\nAverage value = " << average << "\n\n";
return(0);
}
However, my problem is this: I need to convert the following loop into assembly, what is the best method of doing this based on the example I've been given? I'm really struggling with assigning the temp_char variable to an array variable.
By following loop I mean the encrypt_chars function loop
#define MAXCHARS 6
#define dollarchar '$' // string terminator
char OChars[MAXCHARS],
EChars[MAXCHARS],
DChars[MAXCHARS] = "Soon!"; // Global Original, Encrypted, Decrypted character strings
//----------------------------- C++ Functions ----------------------------------------------------------
void get_char(char& a_character)
{
cin >> a_character;
while (((a_character < '0') | (a_character > 'z')) && (a_character != dollarchar))
{
cout << "Alphanumeric characters only, please try again > ";
cin >> a_character;
}
}
//-------------------------------------------------------------------------------------------------------------
void get_original_chars(int& length)
{
char next_char;
length = 0;
get_char(next_char);
while ((length < MAXCHARS) && (next_char != dollarchar))
{
OChars[length++] = next_char;
get_char(next_char);
}
}
void encrypt_chars(int length, char EKey)
{
char temp_char; // char temporary store
for (int i = 0; i < length; i++) // encrypt characters one at a time
{
temp_char = OChars[i]; // temp_char now contains the address values of the individual character
__asm
{
push eax // Save values contained within register to stack
push ecx
movzx ecx, temp_char
push ecx // Push argument #2
lea eax, EKey
push eax // Push argument #1
call encrypt4
add esp, 8 // Clean parameters of stack
mov temp_char, al // Move the temp character into a register
pop ecx
pop eax
}
EChars[i] = temp_char; // Store encrypted char in the encrypted chars array
}
return;
// Inputs: register EAX = 32-bit address of Ekey,
// ECX = the character to be encrypted (in the low 8-bit field, CL).
// Output: register EAX = the encrypted value of the source character (in the low 8-bit field, AL).
__asm
{
encrypt4:
push ebp // Set stack
mov ebp, esp // Set up the base pointer
mov eax, [ebp + 8] // Move value of parameter 1 into EAX
mov ecx, [ebp + 12] // Move value of parameter 2 into ECX
push edi // Used for string and memory array copying
push ecx // Loop counter for pushing character onto stack
not byte ptr[eax] // Negation
add byte ptr[eax], 0x04 // Adds hex 4 to EKey
movzx edi, byte ptr[eax] // Moves value of EKey into EDI using zeroes
pop eax // Pop the character value from stack
xor eax, edi // XOR character to give encrypted value of source
pop edi // Pop original address of EDI from the stack
rol al, 1 // Rotates the encrypted value of source by 1 bit (left)
rol al, 1 // Rotates the encrypted value of source by 1 bit (left) again
add al, 0x04 // Adds hex 4 to encrypted value of source
mov esp, ebp // Deallocate values
pop ebp // Restore the base pointer
ret
}
//--- End of Assembly code
}
int main(void)
{
int char_count; // The number of actual characters entered (upto MAXCHARS limit).
char EKey; // Encryption key.
cout << "\nPlease enter your Encryption Key (EKey) letter: "; get_char(EKey);
cout << "\nNow enter upto " << MAXCHARS << " alphanumeric characters:\n";
get_original_chars(char_count);
cout << "\n\nOriginal source string = " << OChars << "\tHex = ";
for (int i = 0; i<char_count; i++) cout << hex << setw(2) << setfill('0') << ((int(OChars[i])) & 0xFF) << " ";
encrypt_chars(char_count, EKey);
cout << "\n\nEncrypted string = " << EChars << "\tHex = ";
for (int i = 0; i<char_count; i++) cout << ((int(EChars[i])) & 0xFF) << " ";
decrypt_chars(char_count, EKey);
cout << "\n\nDecrypted string = " << DChars << "\tHex = ";
for (int i = 0; i<char_count; i++) cout << ((int(DChars[i])) & 0xFF) << " ";
cout << "\n\nPress a key to end...";
while (!_kbhit()); //hold the screen until a key is pressed
return (0);
}
offering a cookie to the best explained (step-by-step) answer/ solution!!
EDIT: Disassembly code generated from the loop etc:
http://pastebin.com/u5MgJ2SW
notice line 32 where it says mov cl,byte ptr [eax+0CC0320h] Unless you
can tell me how to convert that into 'normal asm code'
mov cl,byte ptr [eax+0CC0320h]: eax at this point contains the value of i, 0CC0320h is the address of OChars, i.e. its begining. So, the "normal" asm code is as follows:
__asm {
mov eax, i
mov cl, byte ptr OChars[eax]
mov temp_char, cl
}
I'm writing simple mix of c++ and nasm assembly atm and dont understand why the results are different inside and outside of the "cout". Maybe this is some kind of exception however I would like to know the difference.Thanks for any help.
C++ PART
#include <iostream>
#include <cstring>
using namespace std;
extern "C" unsigned int quot (unsigned int, unsigned int);
extern "C" unsigned int remainder (unsigned int, unsigned int);
int main()
{
unsigned int i=0, j=0, k=0;
cout << "Numbers 'x y'" << endl;
cin >> i >> j;
k = quot(i,j);
cout<< "Result: " <<k;
k = remainder(i,j);
cout <<" r. "<< k <<endl;
cout << "Result: "<<quot(i,j)<<" r. "<<remainder(i,j)<<endl;
return 0;
}
NASM
quot and reminder functions are almost the same. the only difference is commented in the code
section .data
section .text
global quot
quot:
; intro
push ebp
mov ebp,esp
xor edx, edx
mov eax, [ebp+8]
mov ebx,[ebp+12]
div ebx
; DIFFERENCE: in remainder we have additionaly
; mov eax, edx
mov esp,ebp
pop ebp
ret
RESULTS
For 12 5 input we expect Result: 2 r. 2 but we obtain.
Result: 2 r. 2
Result: 2 r. 5
You have to preserve value of ebx in your asm functions (see http://en.wikipedia.org/wiki/X86_calling_conventions#cdecl). Violating the calling convention may result in various range of errors, from subtle to crashes.
Use ecx instead of ebx, or try div dword ptr [ebp+12].