I'm currently trying to link assembly functions to my C code driver for a college assignment. Upon executing the program, I get a seg fault error.
Below will include what's in my C file, ASM file, and the info from the GDB debugger.
C code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void add(char*, char*); //would extern be needed here maybe?
int main(){
int choice;
char num1[3];
char num2[3];
printf("Welcome to the back and forth program!\n\n");
do{
printf("What would you like to do?\n\n");
printf("1. Add two numbers together.\n");
printf("2. Find if a string is a palindrome. (ASM Version)\n");
printf("3. Find the factorial of a number.\n");
printf("4. Find if a string is a palindrome. (C Version)\n");
printf("5. Exit Program.\n\n");
printf("choose 1-5: ");
scanf("%d", &choice);
getchar();
while(choice < 1 || choice > 5){
printf("\nPlease choose an option between 1 and 5.\n");
scanf("%d", &choice);
getchar();
}
switch(choice){
case 1:
printf("\n*Add two numbers together*\n\n");
printf("Please enter a number: ");
fgets(num1, 1024, stdin);
num1[strlen(num1) - 1] = '\0';
printf("\nPlease enter a second number: ");
fgets(num2, 1024, stdin);
num2[strlen(num2) - 1] = '\0';
add(num1, num2);
printf("\nResult: %s\n", num2);
case 2:
case 3:
case 4:
case 5:
printf("\nThanks for using!\n");
break;
}
}while(choice != 5);
return 0;
}
One thing to note here, is that my professor is specifically stating I read in the two numbers as strings, and then use the atoi()
function in assembly to convert from string to int.
Now, my ASM code:
BITS 32
GLOBAL add
EXTERN atoi
section .data
section .bss
section .text
add:
push ebp
mov ebp, esp
push eax
call atoi
push ebx
call atoi
mov eax, [ebp 8]
mov ebx, [ebp 12]
add eax, ebx
pop ebx
ret
Since I'm required to call atoi()
from my Assembly function, I'd assume it's necessary to use a stack.
Finally, what the GDB debugger is saying:
Program received signal SIGSEGV, Segmentation fault. 0xffffcdbc in ?? ()
A note on the debugger error: when stepping through the program, it says this error once it reaches add(num1, num2)
.
For some other important information, I'm using the GCC compiler, NASM compiler, Intel Assembler i386, and am running Debian 10 x86_64 in a virtual machine via VirtualBox.
Any help on the matter would be greatly appreciated!
CodePudding user response:
The first problem that I saw it's that you used:
fgets(num1, 1024, stdin);
but num1 have only 3 bytes as a buffer, but this is not the root cause for the segmentation fault.
Another problem was that you declared your add
function as:
void add(char*, char*);
. I think it's easier to declare it as int add(char*, char*);
and use the result from this function as the sum of both numbers.
The problem was in the assembly code, you didn't use the right parameter. For example in this part:
push eax
call atoi
push ebx
call atoi
You used eax
and ebx
as parameters for atoi
, but the parameters for add
function are in [ebp 8]
and [ebp 12]
. After the call you need to be sure that the stack is clean and you need to use add esp, 4
(because it's only one parameter)
Another thing to remember is that after call atoi
the result will be stored in eax
register and because you call atoi
after atoi
you will lose the first result. You need to store the result from the first atoi
(on stack/local variable) and then add it to the next result from the second call to atoi
. I will put my version of C code and assembly that worked on 32 BITS.
C code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int add(char*, char*); //would extern be needed here maybe?
int main(){
int choice;
int sum;
char num1[3];
char num2[3];
printf("Welcome to the back and forth program!\n\n");
do{
printf("What would you like to do?\n\n");
printf("1. Add two numbers together.\n");
printf("2. Find if a string is a palindrome. (ASM Version)\n");
printf("3. Find the factorial of a number.\n");
printf("4. Find if a string is a palindrome. (C Version)\n");
printf("5. Exit Program.\n\n");
printf("choose 1-5: ");
scanf("%d", &choice);
getchar();
while(choice < 1 || choice > 5){
printf("\nPlease choose an option between 1 and 5.\n");
scanf("%d", &choice);
getchar();
}
switch(choice){
case 1:
printf("\n*Add two numbers together*\n\n");
printf("Please enter a number: ");
scanf("%s", num1);
printf("\nPlease enter a second number: ");
scanf("%s", num2);
sum = add(num1, num2);
printf("\nResult: %d\n", sum);
case 2:
case 3:
case 4:
case 5:
printf("\nThanks for using!\n");
break;
}
}while(choice != 5);
return 0;
}
Assembly code:
BITS 32
GLOBAL add
EXTERN atoi
section .data
section .bss
section .text
add:
push ebp
mov ebp, esp
push dword [ebp 8]
call atoi
add esp, 4
push eax
push dword [ebp 12]
call atoi
add esp, 4
pop ecx
add eax, ecx
leave
ret
CodePudding user response:
Can you try increasing array size ? Most of the times accessing array element outside it's defined length is reason for Segmentation Fault.