Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

WRITE A PROGRAM IN ARM ASSEMBLY LANGUAGE PROGRAMMING WRITE A PROGRAM IN ARM ASSE

ID: 3862722 • Letter: W

Question

WRITE A PROGRAM IN ARM ASSEMBLY LANGUAGE PROGRAMMING

WRITE A PROGRAM IN ARM ASSEMBLY LANGUAGE PROGRAMMING

WRITE A PROGRAM IN ARM ASSEMBLY LANGUAGE PROGRAMMING

WRITE A PROGRAM IN ARM ASSEMBLY LANGUAGE PROGRAMMING

WRITE A PROGRAM IN ARM ASSEMBLY LANGUAGE PROGRAMMING

WRITE A PROGRAM IN ARM ASSEMBLY LANGUAGE PROGRAMMING

WRITE A PROGRAM IN ARM ASSEMBLY LANGUAGE PROGRAMMING

WRITE A PROGRAM IN ARM ASSEMBLY LANGUAGE PROGRAMMING

WRITE A PROGRAM IN ARM ASSEMBLY LANGUAGE PROGRAMMING

Checksum of data Calculate the checksum of a series of 8-bit numbers. The length of the series is defined by the variable LENGTH. The label START indicates the start of the table. Store the checksum in the variable CHECKSUM. The checksum is formed by adding all the numbers in the list, ignoring the carry over (or overflow). Note: Checksums are often used to ensure that data has been correctly read. A checksum calcu- lated when reading the data is compared to a checksum that is stored with the data. If the two checksums do not agree, the system will usually indicate an error, or automatically read the data again. Sample Problem: Input: LENGTH 00000003 (Number of items) (Start of data table) START 28 55 26 Output CHECKSUM 28 55 26 (Data Checksum) 00101000 01010101 (55) 01111101 (7D) 00100110 (26) 10100011 (A3)

Explanation / Answer

#include <iostream> //I/O

#include <fstream> //File I/O

//#include <intrin.h> //Win32 only, endian functions

#define SWAP_UINT16(x) (((x) >> 8) | ((x) << 8))

//By JohnScipione, Thanks!

int logicalRightShift(int x, int n) {

return (unsigned)x >> n;

}

int arithmeticRightShift(int x, int n) {

if (x < 0 && n > 0)

return x >> n | ~(~0U >> n);

else

return x >> n;

}

unsigned int CalcSlot1Checksum(char * memblock2, char * r12mem);

unsigned int CalcSlot2Checksum(char * memblock2, char * r12mem);

unsigned int CalcFileChecksum(char * memblock2, char * r12mem);

int main(int argc, char* argv[])

{

//Read stream

std::ifstream InternalmemStream;

//Open file by its end (EOF) so we'll know it's exact size

InternalmemStream.open("internalmem.dat", std::ios::in | std::ios::binary | std::ios::ate);

//Check

if (!InternalmemStream.is_open())

{

std::cout << "[!] Can't Open internalmem.dat";

exit(EXIT_FAILURE);

}

char * r12mem;

//Get rom size

std::streampos size = InternalmemStream.tellg();

std::cout << "[>] Internal Memory Size: " << size << " bytes" << std::endl;

//Allocate memory for it

r12mem = new char[size];

//Seek to the start of the file

InternalmemStream.seekg(0, std::ios::beg);

//Read the ROM

InternalmemStream.read(r12mem, size);

std::cout << "[>] Internal Memory Loaded" << std::endl;

InternalmemStream.close();

//File stream 'fstream' can both read and write to files

std::fstream saveStream;

saveStream.open("Transformers.sav", std::ios::in | std::ios::out | std::ios::binary | std::ios::ate);

if (!saveStream.is_open())

{

std::cout << "[!] Can't Open Transformers.sav";

exit(EXIT_FAILURE);

}

char * memblock2;

std::streampos size2 = saveStream.tellg();//Since we opened the file by it's end we can retrieve it's size

std::cout << "[>] Savegame Size: " << size2 << " bytes" << std::endl;

memblock2 = new char[size2];

saveStream.seekg(0, std::ios::beg);//The we just seek (move) to the begining of the file (0x0)

saveStream.read(memblock2, size2);

//We are not closing the stream since we'll use it to write

unsigned int check1, check2, check3;

inicio:

system("cls");

int opt;

std::cout << " ##### Transformers Checksum Tool #####" << std::endl << std::endl;

std::cout << "1. Calc Slot 1 checksum" << std::endl;

std::cout << "2. Calc Slot 2 checksum" << std::endl;

std::cout << "3. Calc File checksum" << std::endl;

std::cout << "4. Save changes and exit" << std::endl << std::endl;

std::cout << "> ";

std::cin >> opt; std::cout << std::endl;

switch (opt)

{

case 1:

check1 = CalcSlot1Checksum(memblock2, r12mem);//Get checksum in little endian. Must be writen to file in big endian

saveStream.seekg(0xFB);//Checksum 1 pos

saveStream.write(reinterpret_cast<const char *>(&check1), sizeof(check1)); //Yep correct way of doing this

std::cout << check1;

std::cin.get();

std::cin.get();

break;

case 2:

check2 = CalcSlot2Checksum(memblock2, r12mem);

saveStream.seekg(0x1E0);//Checksum 2 pos

saveStream.write(reinterpret_cast<const char *>(&check2), sizeof(check2)); //Yep correct way of doing this

std::cin.get();

break;

case 3:

check3 = CalcFileChecksum(memblock2, r12mem);

saveStream.seekg(0x1FE);//Checksum 3 pos

saveStream.write(reinterpret_cast<const char *>(&check3), sizeof(check3)); //Yep correct way of doing this

break;

case 4:

saveStream.close();

exit(EXIT_SUCCESS);

break;

}

goto inicio;

}

unsigned int CalcSlot1Checksum(char * memblock2, char * r12mem)

{

//Simulates registers

unsigned int r0 = 0x00000000; //Seed. Will also store final checksum

unsigned int r1 = 0x0000001C; //Memory pointer to internal memory

unsigned int r2 = 0x000000DF; //Counter

unsigned int r3 = 0x00000000; //Byte pointed by r1

bool breaker = false;

while (1) //Simulate loop to calculate crc

{

r3 = memblock2[r1]; r1++; //Where r1 is address where savedata is 0x0 for slot 1 and 0x00000100 for slot 2 ||THIS FAILS||

//COOL PATCH TO CORRECTLY FIX/LOAD R3 ADDRESSES

r3 = r3 & 0x000000FF;

if (r2 == 0){ breaker = true; }

r2 = r2 - 1;

r3 = r3 ^ (arithmeticRightShift(r0, 0x8));

r3 = r3 << 1;

if (r3 >= 0x2710){

std::cout << "R2: " << std::hex << r2 << std::endl;

std::cout << "call to r12 mem very big: " << r3;

std::cin.get();

}

//Gets byte at r3, merges it with byte at r3+1

r3 = ((unsigned char)r12mem[r3] << 8) | (unsigned char)r12mem[r3 + 1]; //forget this -> It's ok but compiler fucks it when using [r3+1] In addition you have to use little endian bitch

r3 = _byteswap_ushort(r3); //Since nds is little endian and my PC uses big endian I'll convert it when reading from memory

//Unsigned int is 2 bytes -> 16 bits -> ushort

//Boring XORs and shifts right here..

r0 = r3 ^ (r0 << 0x8);

r0 = r0 << 0x10;

r0 = logicalRightShift(r0, 0x10);

if (breaker == true){ break; }

}

std::cout << "Slot 1 Checksum(r0): " << std::hex << r0 << std::endl;

return r0;

}

unsigned int CalcSlot2Checksum(char * memblock2, char * r12mem)

{

//Simulates registers

unsigned int r0 = 0x00000000; //Seed. Will also store final checksum

unsigned int r1 = 0x00000100; //Memory Location where data to be checksumed starts

unsigned int r2 = 0x000000DF; //Counter

unsigned int r3 = 0x00000000; //Stores the byte pointed by r1 to perform operations on it

bool breaker = false;

while (1) //Simulate loop to calculate crc

{

r3 = memblock2[r1]; r1++; //Where r1 is address where savedata is 0x0 for slot 1 and 0x00000100 for slot 2 ||THIS FAILS||

//COOL PATCH TO CORRECTLY FIX/LOAD R3 ADDRESSES

r3 = r3 & 0x000000FF;

if (r2 == 0){ breaker = true; }

r2 = r2 - 1;

r3 = r3 ^ (arithmeticRightShift(r0, 0x8)); //GOOD UNTIL HERE

r3 = r3 << 1; //Yay! //GOOD UNTIL HERE

if (r3 >= 0x2710){

std::cout << "R2: " << std::hex << r2 << std::endl;

std::cout << "call to r12 mem very big: " << r3;

std::cin.get();

}

//YEEEEAH IT WORRKS! gets byte at r3, merges it with byte at r3+1

r3 = ((unsigned char)r12mem[r3] << 8) | (unsigned char)r12mem[r3 + 1]; //forget this -> It's ok but compiler fucks it when using [r3+1] In addition you have to use little endian bitch

r3 = _byteswap_ushort(r3); //Since nds is little endian and my PC uses big endian I'll convert it when reading from memory

// ushort = 2 bytes -> unsigned 16 bits

r0 = r3 ^ (r0 << 0x8); //Yay! r3 = 0x00004084 this xor is the one that increments r0

r0 = r0 << 0x10;

r0 = logicalRightShift(r0, 0x10);

if (breaker == true){ break; }

//std::cin.get();

}

std::cout << "Slot 2 Checksum(r0): " << std::hex << r0 << std::endl;

std::cin.get();

return r0;

}

unsigned int CalcFileChecksum(char * memblock2, char * r12mem)

{

//Simulates registers

unsigned int r0 = 0x0000BEEF; //Seed. Will also store final checksum

unsigned int r1 = 0x00000000; //Memory Location where data to be checksumed starts

unsigned int r2 = 0x000001FD; //Counter

unsigned int r3 = 0x00000000; //Stores the byte pointed by r1 to perform operations on it

bool breaker = false;

while (1) //Simulate loop to calculate crc

{

r3 = memblock2[r1]; r1++; //Where r1 is address where savedata is 0x0 for slot 1 and 0x00000100 for slot 2 ||THIS FAILS||

//COOL PATCH TO CORRECTLY FIX/LOAD R3 ADDRESSES

r3 = r3 & 0x000000FF;

if (r2 == 0){ breaker = true; }

r2 = r2 - 1;

r3 = r3 ^ (arithmeticRightShift(r0, 0x8)); //GOOD UNTIL HERE

r3 = r3 << 1; //Yay! //GOOD UNTIL HERE

if (r3 >= 0x2710){

std::cout << "R2: " << std::hex << r2 << std::endl;

std::cout << "call to r12 mem very big: " << r3;

std::cin.get();

}

//Gets byte at r3, merges it with byte at r3+1

r3 = ((unsigned char)r12mem[r3] << 8) | (unsigned char)r12mem[r3 + 1]; //forget this -> It's ok but compiler fucks it when using [r3+1] In addition you have to use little endian bitch

//r3 = _byteswap_ushort(r3); //Since nds is little endian and my PC uses big endian I'll convert it when reading from memory

r3 = SWAP_UINT16(r3);

r0 = r3 ^ (r0 << 0x8); //Yay! r3 = 0x00004084 this xor is the one that increments r0

r0 = r0 << 0x10;

r0 = logicalRightShift(r0, 0x10);

if (breaker == true){ break; }

}

std::cout << "File Checksum(r0): " << std::hex << r0 << std::endl;

std::cin.get();

return r0;

}