0

I am student of 1 year of IT and now we have inline asembly. I trying to make function that will add two numbers but i got "floating point error"

#include <iostream>

int sum(int a, int b){
    int wynik;
    __asm__(
    "movl 8(%%ebp), %%eax;"
    "addl 12(%%ebp), %%eax;"
    "movl %%eax, %0;"
    : "+r"(wynik)
    :
    : "cc"
   );
    return wynik;
};

int main(void)
{
    int a, b;
    a = 3;
    b = 7;
    std::cout << sum(a, b) << "\n";
    return 0;
}
phuclv
  • 37,963
  • 15
  • 156
  • 475
Hyacin
  • 9
  • 3
  • Read the chapter on inline asm again, specifically the constraints. `wynik` isn't read by the instruction at all. It's also not written to like it should. You are also not passing in `a` and `b` as inputs. The clobber `cc` is also wrong. And to top it all the whole thing is utterly pointless since C is perfectly able to add 2 int. – Goswin von Brederlow Jun 04 '22 at 10:34
  • @GoswinvonBrederlow thanks, i know this is pointless but we're going to have a test on things like this. – Hyacin Jun 04 '22 at 12:21
  • 1
    @GoswinvonBrederlow It's not utterly pointless if the purpose is to learn how to use GCC's inline assembly extension. – xiver77 Jun 04 '22 at 13:52
  • GCC's online doc (https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html) explains every single thing you need. Maybe someone can provide you code that works, but I think you need to first understand what you are doing. – xiver77 Jun 04 '22 at 13:54
  • The problem is that I'm not sure what part confuses you. If you know the basics of x86 assembly, then a 10~15 minute read of the online doc will get you working code. If you don't, then this question helps you nothing. – xiver77 Jun 04 '22 at 13:59
  • @GoswinvonBrederlow: The `"cc"` clobber isn't *wrong* per-se, x86 `add` does write FLAGS. It's only redundant because GNU C inline asm for x86 and x86-64 implicitly has a `"cc"` clobber. The thing that's wrong with the clobber list is omitting `"eax"`. Of course that's one of many problems, like making assumptions about EBP instead of using input operands. That might happen to work in a debug build in 32-bit mode, but utterly defeat the purpose of using *inline* assembly. `wynik` *is* written by `"movl %%eax, %0;"`, but prob. you mean it should've been initialized in C since `"+r"` reads it – Peter Cordes Jun 05 '22 at 03:42
  • @PeterCordes Close. But I mean the flag says `wynik` will be read but it never is read, only written. But thinking about it again better would be to say that the `a` input and `wynik` output must share a register. Implement `a += b` and let the compiler insert any necessary copies if the value of a is still needed. – Goswin von Brederlow Jun 05 '22 at 03:44
  • @GoswinvonBrederlow: Yes, that's an error we both agree on, but you also commented "*It's also not written to like it should.*" - that's a problem this code doesn't have, other than read-uninitialized at the C level when `"+r"(wynik)` reads the old value to have it in the register it picks for `%0`. Also agreed that `add %[b], %0` would be more efficient, but that's not what this code does, so I wouldn't say they `a` and `wynik` "must" share a register. You can write it inefficiently if you want to, although IDK what the point would be; use non-inline asm if you want to do everything yourself – Peter Cordes Jun 05 '22 at 04:04
  • @xiver77: https://stackoverflow.com/tags/inline-assembly/info has some links to tutorials and a few useful canonical-duplicate Q&As. – Peter Cordes Jun 05 '22 at 04:06
  • @PeterCordes for me it writes just random garbage to the variable. But I'm on 64bit. – Goswin von Brederlow Jun 05 '22 at 04:20
  • @GoswinvonBrederlow: Oh, yeah, but that's because of incorrect handling of input operands. `mov` to `%0` is a valid way to write it at the end. (If you actually built this as 64-bit, like `gcc foo.c` without `-m32`, `movl 8(%%ebp), %%eax` would crash from truncating the frame pointer to 32-bit, so IDK how you ran it at all unless you actually ran it as 32-bit. Unless you changed the source to `16(%%rbp)` instead of `%%edi` to read a non-existent stack-arg? If so, porting it wrong to 64-bit mode doesn't prove anything.) – Peter Cordes Jun 05 '22 at 04:25
  • `g++ -m32 foo.cpp` / `./a.out` prints `10` on my system, like I expected because I didn't enable optimization. (Arch GNU/Linux, x86-64). So I can't reproduce the exact symptoms from this question, and it doesn't describe how SIGFPE was observed. Building as 64-bit code with `g++ foo.cpp` does of course SIGSEGV as expected, `Segmentation fault (core dumped)`. – Peter Cordes Jun 05 '22 at 04:26
  • @PeterCordes You assume I have a frame pointer. – Goswin von Brederlow Jun 05 '22 at 04:28
  • @GoswinvonBrederlow: You do if you leave optimization disabled, which is necessary for this broken code to happen to work. Like I said, I expected this to **happen to** work *only* because I left optimization disabled. We both agree this code not at all the correct approach for reading C vars in inline asm, that's why I closed it as a duplicate of one that explains how, even though the wrong attempt in the other question is different the answer is the same. – Peter Cordes Jun 05 '22 at 04:31

0 Answers0