Converting C to MIPS assembly with pointer - pointers

int x;
int *ptr;
x = 22;
ptr = &x;
*ptr = 100;
How can i convert this code to MIPS language?

You just need to save the memory of x in a register so you can save another word at that address. Here is the solution:
.data
x: .word 22 # int x = 22;
.text
main:
la $t0, x # ptr = &x;
addi $t1, $zero, 100 # add the value 100 in another temporary register
sw $t1, 0($t0) # *ptr = 100;
lw $t3, 0($t0) #if you try to print now the value, you will see that
li $v0, 1 #prints "100"
move $a0, $t3
syscall

Related

Modular Exponentiation using mips

Write a program which prompts the user for three positive numbers x, n and p, and outputs
x^n mod p. Your program should use the recursive version of modular exponentiation.
.text
main:
sub $sp,$sp,4 # save return address on stack
sw $ra, 0($sp)
li $v0, 4 # prompt user for int x
la $a0, S1
syscall
li $v0, 5 # read int
syscall
move $s0, $v0 # cin >> x //and store x in $s0
li $v0, 4 # prompt user for int n
la $a0, S1
syscall
li $v0, 5 # read int
syscall
move $s1, $v0 # cin >> n //and store n in $s1
li $v0, 4 # prompt user for int p
la $a0, S1
syscall
li $v0, 5 # read int
syscall
move $s2, $v0 # cin >> p //and store n in $s2
li $t0, 0 #return value
li $t1, 2 #constant 2
li $t2, 0 #variable y
beq $s0, $zero, L1 #if x == 0, return 1
beq $s1, $zero, L2 #if n is 0, return 0
jal evenMod
L0:
lw $ra, 0($sp) # read registers from stack
lw $s0, 4($sp)
lw $s1, 8($sp)
addi $sp, $sp, 12 # bring back stack pointer
jr $ra
L1:
li $v0, 4
la $a0, S3
syscall
j L0
L2:
li $v0, 4
la $a0, S4
syscall
j L0
L3:
li $v0, 1
move $a0, $s1
syscall
j L0
evenMod:
beq $s0, $zero, L1 #if x == 0, return 1
beq $s1, $zero, L2 #if n is 0, return 0
rem $s3, $s1, $t1 #s3 = s1 % 2
bne $s3, $zero, oddMod #if n%2 == 0, recursive call for odd
div $s1, $s1, 2 #n = n/2
mult $t2, $t2 #y = y*y
rem $t2, $t2, $s2 #y= (y*y)%c
jal evenMod
j L3
oddMod:
beq $s0, $zero, L1 #if x == 0, return 1
beq $s1, $zero, L2 #if n is 0, return 0
rem $s3, $s1, $t1 #s3 = s1 % 2
bne $s3, $zero, evenMod #if n%2 == 0, recursive call for even
rem $s3, $s1, $s2 #s3 = s1 % P
addi $s0, 0 #x stays the same
add $s1, $s1, -1 #n = n-1
addi $s2, 0 #p stays the same
jal oddMod #call oddmod with updated values
mult $t2, $t2 #multiply y*y
rem $t2, $t2, $s2 #y = y%P
j L3
.data
S1:
.asciiz "Enter an integer --> "
S3:
.asciiz "0"
S4:
.asciiz "1"
This is what I have so far, but I'm getting stuck on where the JALs should occur.
C code:
public static int exponentMod(int A, int B, int C) {
//base cases
if (A == 0) return 0;
if (B == 0) return 1;
//If B is even
long y;
if (B % 2 == 0) {
y = exponentMod(A, B / 2, C);
y = (y * y) % C;
}
//if B is odd
else {
y = A % C;
y = (y * exponentMod(A, B - 1, C) % C) % C;
}
//return the modular exponent
return (int)((y + C) % C);
}
Transformation, still in C, to if-goto-label as follows:
public static int exponentMod(int A, int B, int C) {
//base cases
if (A != 0) goto endIf1;
return 0;
endIf1:
if (B != 0) goto endIf2;
return 1;
endIf2:
long y;
if (B % 2 != 0) goto elseIf3;
// B is even
y = exponentMod(A, B / 2, C);
y = (y * y) % C;
goto endIf3;
elseIf3:
// B is odd
y = A % C;
y = (y * exponentMod(A, B - 1, C) % C) % C;
endIf3:
//return the modular exponent
return (int)((y + C) % C);
}
The control flow has been converted to the if-goto-label style of assembly, using logical transformations.  (Note that the above transformation remains valid and runnable C, and will run the same as the structured-statement original.)  The if-goto-label version is closer to assembly. 
Of course, there are many other ways to translate the control flow, such as moving blocks of code to different places; however, I prefer the above form that stays true to the statement ordering of original C code, making it easier to follow when comparing the original and the assembly version.
So, what's left to do is transform the non-control flow statements and expressions, which should appear in orientation exactly where they are in this transformation result.

Array of pointers, VirtualAlloc and RtlMoveMemory. MASM, some kind of problem

Does anybody know how to fix the addElement function so it ends up as another element in the array. The idea is a dynamic array, where arrayPtr is a pointer to the first element, then new elements can be added dynamically and kept track of by increasing the arrayPtr value. So in-fact I think what it would end up being is an array of pointers to DbRecord structs in memory. Allocated by VirtualAlloc and copied by RtlMoveMemory. I am kinda of hung up on RtlMoveMemeory line. I feel like my line of thinking is correct.
.386
.model flat, stdcall
option casemap :none
include windows.inc
include user32.inc
include kernel32.inc
addElement PROTO: ptr DbRecord
.data?
DbRecord struct
Id dd ?
WordOne db 32 dup(?) ; db is define byte, set value of byte
WordTwo db 32 dup(?)
WordThree db 32 dup(?)
Year dd ?
DbRecord ends
arrayPtr dd ? ; pointer in memory to start of array
newElementPointer DbRecord <>
hStdOut dd ?
bytesWritten dd ?
.data
arrayCount dd 0
hello db 'Hello World!', 0
.code
main proc
LOCAL DbRecord01:DbRecord
mov [DbRecord01.Id], 1;
; any other way than one character at a time?
mov byte ptr [DbRecord01.WordOne], 'D'
mov byte ptr [DbRecord01.WordOne + 1], 'o'
mov byte ptr [DbRecord01.WordOne + 2], 'g'
mov byte ptr [DbRecord01.WordOne + 3], 0
mov byte ptr [DbRecord01.WordTwo], 'C'
mov byte ptr [DbRecord01.WordTwo + 1], 'a'
mov byte ptr [DbRecord01.WordTwo + 2], 't'
mov byte ptr [DbRecord01.WordTwo + 3], 0
mov byte ptr [DbRecord01.WordThree], 'E'
mov byte ptr [DbRecord01.WordThree + 1], 'y'
mov byte ptr [DbRecord01.WordThree + 2], 'e'
mov byte ptr [DbRecord01.WordThree + 3], 0
mov [DbRecord01.Year], 2022;
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov [hStdOut], eax
invoke WriteConsole, hStdOut, offset hello, sizeof hello, offset bytesWritten, NULL
invoke addElement, addr DbRecord01
ret
main endp
addElement proc DbRecordPointer: ptr DbRecord
invoke VirtualAlloc, NULL, sizeof DbRecord, MEM_COMMIT, PAGE_READWRITE ; I beleive store a memory address in eax
invoke RtlMoveMemory, DbRecord ptr [eax], DbRecordPointer, sizeof DbRecord ; but how to use that memory address here?
ret
addElement endp
end main
EDIT/Update:
So yes part of the answer is just passing in eax.
I am here now
How do I get the value of eax ("memory location from VirtualAlloc",) where data was copied into arrayPtr (arrayPtr + count * sizeof DbRecord)
.386
.model flat, stdcall
option casemap :none
include windows.inc
include user32.inc
include kernel32.inc
addElement PROTO: ptr DbRecord
.data?
DbRecord struct
Id dd ?
WordOne db 32 dup(?) ; db is define byte, set value of byte
WordTwo db 32 dup(?)
WordThree db 32 dup(?)
Year dd ?
DbRecord ends
arrayPtr dword ? ; pointer in memory to start of array
; newElementPointer DbRecord <>
hStdOut dd ?
bytesWritten dd ?
.data
arrayCount dd 0
hello db 'Hello World!', 0
.code
main proc
LOCAL DbRecord01:DbRecord
mov [DbRecord01.Id], 1;
; any other way than one character at a time?
mov byte ptr [DbRecord01.WordOne], 'D'
mov byte ptr [DbRecord01.WordOne + 1], 'o'
mov byte ptr [DbRecord01.WordOne + 2], 'g'
mov byte ptr [DbRecord01.WordOne + 3], 0
mov byte ptr [DbRecord01.WordTwo], 'C'
mov byte ptr [DbRecord01.WordTwo + 1], 'a'
mov byte ptr [DbRecord01.WordTwo + 2], 't'
mov byte ptr [DbRecord01.WordTwo + 3], 0
mov byte ptr [DbRecord01.WordThree], 'E'
mov byte ptr [DbRecord01.WordThree + 1], 'y'
mov byte ptr [DbRecord01.WordThree + 2], 'e'
mov byte ptr [DbRecord01.WordThree + 3], 0
mov [DbRecord01.Year], 2022;
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov [hStdOut], eax
invoke WriteConsole, hStdOut, offset hello, sizeof hello, offset bytesWritten, NULL
invoke addElement, addr DbRecord01
ret
main endp
addElement proc uses edx DbRecordPointer: ptr DbRecord
Local newElementPointer: Dword
invoke VirtualAlloc, NULL, sizeof DbRecord, MEM_COMMIT, PAGE_READWRITE ; I beleive store a memory address in eax
mov newElementPointer, eax
;invoke RtlMoveMemory, newElementPointer , DbRecordPointer, sizeof DbRecord ; but how to use that memory address here?
invoke RtlMoveMemory, eax , DbRecordPointer, sizeof DbRecord
mov edx, arrayCount
inc edx
mov arrayCount, edx
;mov dword ptr [arrayPtr+arrayCount], eax
ret
addElement endp
end main

Multidimensional char string Array initialization and usage for ESP32 MCUs with PSRAM

I have an ESP32 microcontroller with 64Mb PSRAM onboard. How can i move into PSRAM a multidimensional array I have on my code , too big to fit into the ESP32 RAM?
Let's assume I need a 3D multidimensional array of char string, piBuffer , with dimensions 10x10x10 and I need to store it in the SPI PSRAM IC and not on the MCU's internal RAM
char ****piBuffer = NULL; //pointer to pointer
int nRow = 10; //variable store size of 1st dimension
int nColumn = 10; //variable store size of 2nd dimension
int dim3 = 10; // variable store size of 3rd dimension
int iRow = 0; //Variable for looping 1st dimension, "row"
int iCol = 0; //Variable for looping 2nd dimension "column"
int i3D = 0; //Variable for looping 3rd dimension
First one needs to allocate memory for the 1st dimension, "rows":
piBuffer = (char ****)heap_caps_malloc(nRow * sizeof(char***), MALLOC_CAP_SPIRAM);
//Check memory validity
if(piBuffer == NULL){
Serial.println("FAIL");
}
Next, one needs to allocate memory for the 2nd dimension, "columns":
for (iRow =0 ; iRow < nRow ; iRow++){
piBuffer[iRow] = (char ***)heap_caps_malloc(nColumn * sizeof(char**), MALLOC_CAP_SPIRAM);
//Check memory validity
if(piBuffer[iRow] == NULL){
// freeAllocatedMemory(piBuffer,iRow);
Serial.println("FAIL");
}
}
Next, one need to allocate memory for the 3rd dimension, "dim3":
for (iRow =0 ; iRow < nRow ; iRow++){
for (iCol =0 ; iCol < nColumn ; iCol++){
piBuffer[iRow][iCol] = (char **)heap_caps_malloc(dim3 * sizeof(char*), MALLOC_CAP_SPIRAM);
//Check memory validity
if(piBuffer[iRow] == NULL){
//freeAllocatedMemory(piBuffer,iRow);
Serial.println("FAIL");
}
}
}
Finally, one need to allocate memory for the char string size it self. On the piece of code below char strings are initialized with a 20 char string size:
for (iRow =0 ; iRow < nRow ; iRow++) {
for (iCol =0 ; iCol < nColumn ; iCol++){
for (i3D =0 ; i3D < dim3 ; i3D++){
piBuffer[iRow][iCol][i3D] = (char *)heap_caps_malloc(20 * sizeof(char), MALLOC_CAP_SPIRAM);
}
}
}
The code above was only to initialize the multidimensional 3D array of char strings. To use it and assign (set) char string values to it one can do it like so:
for (iRow =0 ; iRow < nRow ; iRow++) {
for (iCol =0 ; iCol < nColumn ; iCol++){
for (i3D =0 ; i3D < dim3 ; i3D++){
String("MTasdfsa").toCharArray(piBuffer[iRow][iCol][i3D], String("MTasdfsa").length()+1);
}
}
}
To get , output or print values stored into the multidimensional array on can do it like the next piece of code:
for (iRow =0 ; iRow < nRow ; iRow++) {
for (iCol =0 ; iCol < nColumn ; iCol++) {
for (i3D =0 ; i3D < dim3 ; i3D++){
Serial.println("piBuffer["+String(iRow)+"]["+String(iCol)+"]["+String(i3D)+"] = " +String(piBuffer[iRow][iCol][i3D]));
}
}
}
At the end, is required to free the memory block reserved for the multidimensional array. This can be done using a function, freeAllocatedMemory, defined as follows:
//Free Allocated memory
void freeAllocatedMemory(int ***piBuffer, int nRow, int nColumn, int dim3){
int iRow = 0;
int iCol=0;
int i3D=0;
for (iRow =0; iRow < nRow; iRow++){
for (iCol =0 ; iCol < nColumn ; iCol++){
for (i3D =0 ; i3D < dim3 ; i3D++){
free(piBuffer[iRow][iCol][i3D]); // free allocated memory
}
free(piBuffer[iRow][iCol]); // free allocated memory
}
free(piBuffer[iRow]); // free allocated memory
}
free(piBuffer);
}
One final note
this multidimensional array can be initialized differently, as a 1D array and keep track of memory block positions for the corresponding rows, columns and 3rd dimens. To do it one can use the next math. formula
iRow x nCol +icol + nRow x nCol x i3D
to get or set char string values into the multidimensional array.

Returning a value pointed to by a pointer in x86 NASM

I'm trying to write a function in x86 NASM assembly that takes a pointer to a structure (structure contains pointer to a buffer) and 2 ints (x,y) which then computes the address of the byte containing (x,y) and returns the value in this address. (The buffer contains a bmp file) I have this function written in C and it works fine.
C function
int loadByte(imgInfo* pImg, int x, int y)
{
unsigned char *pPix = pImg->pImg + (((pImg->width + 31) >> 5) << 2) * y + (x >> 3);
return *pPix;
}
x86 function
load_byte:
push ebp ; prologue
mov ebp, esp
lea ecx, [ebp + 8]
mov ecx, [ecx] ; ecx = &imgInfo
mov eax, [ecx+0] ; eax = width
add eax, 31 ; eax = width + 31
sar eax, 5 ; eax = (width + 31) >> 5
sal eax, 2 ; eax = ((width + 31) >> 5) << 2
mul DWORD [ebp+16] ; eax * y
mov edx, [ebp+12] ; edx = x
sar edx, 3 ; edx = x>>3
add eax, edx ; eax = ((width + 31) >> 5) << 2 * y + (x >> 3)
mov edx, [ecx+8] ; edx = &pImg
add eax, edx
mov eax, [eax]
pop ebp ; epilogue
ret
I tried checking if the address computed in both functions is the same so I changed the return of C to return pPix and commented the line mov eax, [eax] in x86 and to my surprise both functions returned the same number but in the unchanged form (as in the code above) the x86 function always returns -1 for some reason. Is return *pPix not equivalent to mov eax, [eax]? What is wrong with my reasoning?
imgInfo struct
typedef struct
{
int width, height;
unsigned char* pImg; //buffer
int cX, cY;
int col;
} imgInfo;
load_byte C declaration
extern int load_byte(imgInfo* pInfo, int x, int y);

How do I swap two pointer values without using third variable

*a=10
*b=20
How to swap them without using the third variable? Output should be like
*a=20
*b=10
Not sure if the interviewer was looking for XOR over something else but it seems you can simply use +, -, and x. Should work if a is bigger or negative as well.
*a+=*b
*b-=*a
*b=*b x -1
*a-=*b
In your example that would give us:
*a+=*b --> *a = 30
*b-=*a --> *b = -10
*b=*b x -1 --> *b = 10
*a-=*b --> *a = 20
Here is a simple code to do so:
#include <stdio.h>
#include <stdlib.h>
void usingXOR(int** x, int** y){
unsigned long long a = (unsigned long long)*x;
unsigned long long b = (unsigned long long)*y;
a = a^b;
b = a^b;
a = a^b;
*x = (int*)a;
*y = (int*)b;
}
void main(){
int x=5;
int y=10;
int* a = &x;
int* b = &y;
//If you only want to swap the values the pointers are pointing to
//Here the addresses the pointers are holding dont get swapped
(*a) = (*a)+(*b);
(*b) = (*a)-(*b);
(*a) = (*a)-(*b);
//If you want to swap addresses in the pointers
//printf("Before swap address a: %p\n", a);
//printf("Before swap address b: %p\n", b);
//usingXOR(&a,&b);
printf("a: %d\n", *a);
printf("b: %d\n", *b);
//printf("After swap address a: %p\n", a);
//printf("After swap address b: %p\n", b);
}

Resources