1

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!

1
  • pop ebx is probably a typo for pop ebp ? Commented Nov 27, 2021 at 0:51

1 Answer 1

2

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

Sign up to request clarification or add additional context in comments.

5 Comments

Awesome!! So, I had the same idea having the add function as int at first, but for some odd reason my professor is requiring me to have that function as void... Thanks for pointing out what you did though! I'm still learning how to pass stuff between ASM and C, and this helps greatly.
Then the asm file needs a couple of changes. You need to overwrite [ebp+8] or [ebp+12] with the integer from eax. But be careful because [ebp+8} and [ebp+12]are addresses and eax is basically an integer.
It's better to write mov [ebp-4], eax instead of the pair add esp, 4 push eax.
@SepRoland Yes, but would be harder to understand.
@MocanuGabriel I'll definitely look into how to do that@Sep Roland I'll also look into that and figure out what that is haha! My ASM class is just an introductory course, but I'm down to learn more about it. Thank you both for your help and input!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.