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)