i need your help troubleshooting. I have a .c file, linked with multiple .S files. when…
- User
i need your help troubleshooting. I have a .c file, linked with multiple .S files. when I am executing the test command that tests all the different mathematical functions with given values, I am receiving a segmentation fault. go through my code and tell me why:
my .c file: #include <stdio.h> int beginProgram(); int add(int n1, int n2); int subtract(int n1, int n2); int multiply(int n1, int n2); int exponentiation(int n1, int n2); int floordivision(int n1, int n2); int bitcounting(int n); int summation(int n1, int n2); int factorial(int n); int modulus(int n1, int n2);
int main () { while (1) {
int input; printf ("Welcome to DanBurr Calcutron\n"); printf ("----------------------------\n"); printf ("Press 1 to begin and list all available commands\n"); printf ("Press 9 to exit program\n"); scanf ("%d", &input); if (input == 1) { beginProgram (); } else if (input == 9) { printf ("Exit command executed\n\n"); break; } else continue; }return 0; }
int beginProgram() { while (1) { int input; printf("Press 0 to add two numbers\n"); printf("Press 1 to subtract two numbers\n"); printf("Press 2 to multiply two numbers\n"); printf("Press 3 to get exponentiation of a number\n"); printf("Press 4 to perform floor division of two numbers\n"); printf("Press 5 to perform bitcounting of a number\n"); printf("Press 6 to find integer summation of two numbers\n"); printf("Press 7 to find factorial of a number\n"); printf("Press 8 to perform modulo division of two numbers\n"); printf("Press 9 to go back to main screen\n"); printf("Enter 10 for test command\n\n"); scanf("%d", &input);
if (input == 9) { printf("Exit called code 9\n\n"); break; }
else if (input == 0) { int n1, n2; printf("Enter first number: \n"); scanf("%d", &n1); printf("Enter second number: \n"); scanf("%d", &n2); int result = add(n1, n2); printf("The result is:%d\n\n", result); }
else if (input == 1) { int n1, n2; printf("Enter first (larger) number: \n"); scanf("%d", &n1); printf("Enter second (smaller) number: \n"); scanf("%d", &n2); int result = subtract(n1, n2); printf("The result is:%d\n\n", result); }
else if (input == 2) { int n1, n2; printf("Enter first number: \n"); scanf("%d", &n1); printf("Enter second number: \n"); scanf("%d", &n2); int result = multiply(n1, n2); printf("The result is:%d\n\n", result); }
else if (input == 3) { int n1, n2; printf("Enter base number: \n"); scanf("%d", &n1); printf("Enter power raising the number to: \n"); scanf("%d", &n2); int result = exponentiation(n1, n2); if(result<0){ printf("Illegal arguments. Try again\n\n"); continue; } else printf("The result is: %d\n\n", result); }
else if (input == 4) { int n1, n2; printf("Enter larger number: \n"); scanf("%d", &n1); printf("Enter number dividing the larger number by: \n"); scanf("%d", &n2); int result = floordivision(n1, n2); if(result<0){ printf("Illegal arguments. Try again\n\n"); continue; } else printf("The result is: %d\n\n", result); }
else if (input == 5) {
int n; printf("Enter number to count bits. Number cannot exceed 32 bits: \n"); scanf("%d", &n); int result = bitcounting(n); printf("The result is:%d\n\n", result); }else if (input == 6) {
int n1, n2; printf("Enter starting(smaller) number: \n"); scanf("%d", &n1); printf("Enter ending(larger) number: \n"); scanf("%d", &n2); int result = summation(n1, n2); printf("The result is:%d\n\n", result); }else if (input == 7)
{ int n; printf("Enter positive number to find factorial. Number cannot exceed 12: \n"); scanf("%d", &n); int result = factorial(n); printf("The result is:%d\n\n", result); }else if (input == 8)
{ int n1, n2; printf("Enter larger number: \n"); scanf("%d", &n1); printf("Enter number dividing the larger number by: \n"); scanf("%d", &n2); int result = modulus(n1, n2); if(result<0){ printf("Illegal arguments. Try again\n\n"); continue; } else printf("The result is: %d\n\n", result); }else if (input == 10) { int n1 = add(100, 199); int n2 = subtract(211999, 9876); int n3 = exponentiation(5, 5); int n4 = floordivision(2004, 5); int n5 = bitcounting(0b100101010001011110011); int n6 = summation(10, 100); int n7 = factorial(6);
printf("100 + 199 = %d\n", n1); printf("211999 - 9876 = %d\n", n2); printf("5^5 = %d\n", n3); printf("floor 2004/5 = %d\n", n4); printf("1s in 100101010001011110011 = %d\n", n5); printf("sum [10,100] = %d\n", n6); printf("6! = %d\n", n7);} else { printf("Wrong input. Please try again\n\n"); continue; }
} return 0; }
my .S files: .syntax unified .align 4 .type add %function .section .text .global add
add: ADD r0, r0, r1 BX lr
.syntax unified .align 4 .type bitcounting %function .section .text .global bitcounting
bitcounting:
PUSH {R4, r5, LR} @ Save registers and link register MOV r5, #0x0 @counter
bitcount_loop: CMP r0, #0x0 BEQ bitcount_end AND r4, r0, #0x1 @extracting first bit in string, storing in r4 CMP r4, #0x1 BLEQ bitcount_increment @if r4=1, counter will be incremented. LSR r0, r0, #0x1 B bitcount_loop
bitcount_increment:
ADD r5, r5, #0x1 BX lr
bitcount_end:
MOV r0, r5 POP {r4, r5, lr} BX lr
.syntax unified .align 4 .type exponentiation %function .section .text .global exponentiation
exponentiation: MOV r0, #0x5 MOV r1, #0x5
CMP r0, #0x0 @ Check if r0=0 BEQ exp_error_check B exp_start
exp_error_check: CMP r1, #0x0 @ Check if r1=0 BNE exp_start MOV r0, #0xFFFFFFFF @if 0^0 condition, error. returns -1 BX lr
exp_start: PUSH {r2, sp, lr} @ To clear r2 once loop is finished MOV r2, #0x1 @ Initialize result to 1 CMP r1, #0x0 @ Compare exponent to 0 BEQ exp_done @ If exponent is 0, return 1
exp_loop: MUL r2, r2, r0 @ Multiply result by base SUB r1, r1, #1 @ Decrement exponent by 1 CMP r1, #0x0 BNE exp_loop @ If exponent is not 0, continue loop
exp_done: MOV r0, r2 @ Move result to r0 for return POP {r2, sp, lr} @ Clear all registers BX lr @ Return
.syntax unified .align 4 .type factorial %function .section .text .global factorial
factorial: CMP r0, #0x0 BEQ baseCase0 BL factorialHelper POP {sp, lr} BX LR
factorialHelper: PUSH {r4, lr} MOV r4, r0 CMP r0, #0x1 BEQ baseCase1 SUB r0, r0, #0x1 BL factorialHelper
baseCase1: MUL r0, r0, r4 POP {r4, lr} BX LR
baseCase0: MOV r0, #0x1 BX LR
.syntax unified .align 4 .type floordivision %function .section .text .global floordivision
floordivision:
cmp r1, #0 @ Compare divisor to 0 bne floordivstart
MOV r0, #0xFFFFFFFF @ If divisor is 0, return -1 BX lrfloordivstart: PUSH {r4, sp, lr} @ To clear registers after returning MOV r4, #0x0 @ To store result
floor_div_loop: cmp r0, r1 @ Compare dividend to divisor blt floor_div_done @ If dividend < divisor, break loop sub r0, r0, r1 @ Subtract divisor from dividend add r4, r4, #1 @ Increment quotient by 1 b floor_div_loop @ Repeat loop
floor_div_done: mov r0, r4 @ Move quotient to r0 for return POP {r4, sp, lr} bx lr @ Return
.syntax unified .align 4 .type modulus %function .section .text .global modulus
modulus: CMP r1, #0x0 @check if dividing by zero. return -1 if yes BEQ modulus_error B modulus_loop
modulus_error: MOV r0, #0xFFFFFFFF POP {sp, lr} BX lr
modulus_loop: CMP r0, r1 @if r0<r1 BLT modulus_end SUB r0, r0, r1 @r0=r0-r1 B modulus_loop
modulus_end: POP {sp, lr} BX lr
.syntax unified .align 4 .type multiply %function .section .text .global multiply
multiply: MUL r0, r0, r1 BX lr
.syntax unified .align 4 .type subtract %function .section .text .global subtract
subtract: CMP r0, r1 @if r0<r1, swap the values BLT subtract_swap B subtract_start
subtract_swap: PUSH {r4} MOV r4, r0 MOV r0, r1 MOV r1, r4 POP {r4} BX lr
subtract_start: SUB r0, r0, r1 BX lr
.syntax unified .align 4 .type summation %function .section .text .global summation
summation:
CMP r0, r1 @if r0>r1, swap BGT sum_swap BEQ sum_equal @if r0==r1, return r0+r1 PUSH {r4, sp, lr} @pushing register to clear them once result is returned B sum_loop
sum_equal: ADD r0, r0, r1 BX lr
sum_swap: PUSH {r4} @pushing temp r4 to clear it once swap is done MOV r4, r0 MOV r0, r1 MOV r1, r4 POP {r4} B summation
sum_loop:
ADD r4, r4, r0 @r4=r4+r0 ADD r0, #0x1 @r0++ CMP r0, r1 @if r0!=r1, loop BLT sum_loop
ADD r4, r4, r1 @to add last number to result MOV r0, r4 POP {r4, sp, lr} BX lr
- Assistant
Based on the code you provided, I found a mistake in the .S file for the "bitcounting" function. In the "bitcount_increment" section, you have "BX lr" which will return to the caller immediately after incrementing the counter (r5), instead of continuing the loop for bit counting. Here's the corrected "bitcount_increment" section:
bitcount_increment: ADD r5, r5, #0x1 B bitcount_loop @ Continue the loop, instead of returning to the caller immediatelyAfter making this change, I would recommend recompiling and testing your code again. If you still encounter any issues, please let me know together with any additional information, and I'll be happy to help.
- User
it is still throwing segmentation fault
- Assistant
I apologize for the inconvenience. I found another issue in your code. In several .S files, you're pushing and popping the stack pointer (
sp) unnecessarily. This may cause issues with your stack and eventually lead to segmentation faults. Please remove the stack pointer fromPUSH { ... }andPOP { ... }lines in your .S files.Here's an example from the "exponentiation" function:
Change this:
PUSH {r2, sp, lr}to this:
PUSH {r2, lr}And this:
POP {r2, sp, lr}to this:
POP {r2, lr}Please apply these changes to all of your .S files where you have used
sp. Once you've made these changes, recompile your code and test it again. If you still encounter any issues, please let me know, and I'll be happy to help.