Tuesday, April 12, 2022

[SOLVED] Inline assembly in C with a jump and two return statements

Issue

I would like to have a void function which prints whether carry (overflow) happened and print the value of the (possibly overflowed) summand.

This is my try, but it does want to compile:

#include <stdio.h>

typedef unsigned long ulong;

void
func()
{
    ulong a = 3;
    ulong b = 1;
    ulong c;

    __asm__(
            "\taddq\t%2, %q0\n"     /* Add b to a and store in c */
            "\tjc\tcarry"
            : "=r" (c)              /* Outputs */
            : "0" (a), "rme" (b)    /* Inputs */
            );
    printf("no carry\nc = %lu\n", c);
    return;
    __asm__("carry:");
    printf("carry\nc = %lu\n", c);
    return;
}

int
main()
{
    func();
}

However, it runs when I remove the first return statement, but then it prints twice if no carry happened.

How can I do this with two return statements?


Solution

You need to use asm goto for that. To do that, add goto after __asm__, change your label to be a C label, pass the label after the clobbers, and then use a %l to refer to it. Here's your program with those fixes applied:

#include <stdio.h>

typedef unsigned long ulong;

void
func()
{
    ulong a = 3;
    ulong b = 1;
    ulong c;

    __asm__ goto(
            "\taddq\t%2, %q0\n"     /* Add b to a and store in c */
            "\tjc\t%l[carry]"
            : "=r" (c)              /* Outputs */
            : "0" (a), "rme" (b)    /* Inputs */
            :
            : carry
            );
    printf("no carry\nc = %lu\n", c);
    return;
    carry:
    printf("carry\nc = %lu\n", c);
    return;
}

int
main()
{
    func();
}

Though as was mentioned in the comments, for this use case in particular, you should just use __builtin_uaddl_overflow instead, unless your goal is just to learn how to jump out of inline assembly.



Answered By - Joseph Sible-Reinstate Monica
Answer Checked By - Dawn Plyler (WPSolving Volunteer)