0

I have to find the distance between two points using inline asm but I've been stuck because the number I get after adding the power of the difference of the two coordinates is too big for a 32bit register.

#include <stdio.h>


void main()
{
// Input
unsigned int Point = 0xFFFFFFFF;
unsigned int PointSet = 0x000A0003
unsigned int dist=0;
/*
every point is a dword and the least significant word is the x coord while the other is the y coord
so for our point it would be (3,10) in decimal and the other point (FFFF,FFFF)
*/

//sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
 __asm
{
    xor eax,eax
    mov eax, dword ptr PointSet[0]
    shr eax,16d //ax is x1
    xor ebx,ebx
    mov bx, word ptr PointSet[0] //bx is y1
    mov ecx, 0xFFFF //x2
    mov edx, 0xFFFF//y2
    sub ecx,eax //(x2-x1)
    sub edx,ebx //(y2-y1)
    imul ecx,ecx //(x2-x1)^2
    imul edx,edx //(x2-x1)^2
    add ecx,edx  //here the number is way too big to stay in a simple 32 bit register
    push esp
    mov  dword ptr[esp], ecx
    fild  dword ptr[esp]
    fsqrt
    fst dword ptr[esp]
    mov ecx,esp

}
printf("%d",dist);
getchar();


}
Govind Parmar
  • 20,656
  • 7
  • 53
  • 85
Lorenz
  • 3
  • 1
  • 1
    Is it a school exercise? Otherwise I see no good reason to do this in inline asm. – Eugene Sh. Aug 21 '17 at 20:46
  • I was about to say – unless this is an exercise, there's no good reason not to let your compiler write that assembly for you. (Hint: I do not recommend cheating, but learning from something that writes good assembly might be a plus – simply compile equivalent source code that explicitly calculates the sum of squares as a 64bit value and learn from the assembly you get.) – Marcus Müller Aug 21 '17 at 20:49
  • 4
    Since you already use the FPU anyway, do the summing there. It has enough bits. PS: `push esp; mov dword ptr[esp], ecx` is a really convoluted way of writing `push ecx` :D Also, your `fst` should be `fstp` to clean up FPU stack. – Jester Aug 21 '17 at 20:51
  • why do you use 32 bit arithmetic? you can do `rax` and the company to handle 64 bit stuff. Are you running on a 32-bit platform? – Serge Aug 21 '17 at 20:58
  • If this is supposed to be efficient, `xor eax,eax` is pointless before `mov eax, dword ptr PointSet[0]`, because the mov-load already overwrites `eax` with no dependency on the old value. See https://stackoverflow.com/questions/33666617/what-is-the-best-way-to-set-a-register-to-zero-in-x86-assembly-xor-mov-or-and#comment55113231_33668295. You should use `movzx ebx, word ptr PointSet[0]` instead of xor-zero and then load. (Or better, you should copy the value from `eax` before you `shr eax`, because you already just loaded it!) – Peter Cordes Aug 21 '17 at 21:23
  • @Serge: MSVC inline-asm syntax isn't available for x86-64, so clearly yes. Writing a stand-alone function in 64-bit asm would make more sense, though. – Peter Cordes Aug 21 '17 at 21:27
  • @PeterCordes I am not familiar with msvc restrictions, but it sounds strange. There should be a way to compile it in a 64-bit mode. Switch to gcc :-) otherwise. – Serge Aug 21 '17 at 21:32
  • 1
    @Serge: MSVC inline-asm sucks in both its design (forces inefficient store/reload to get data in/out) and [apparently also in its implementation](https://stackoverflow.com/questions/3323445/what-is-the-difference-between-asm-and-asm#comment59576185_35959859). Not to mention the magic "leave a retval in eax" and omit the C `return`, which is somehow supported even when inlining. They dropped it for 64-bit, and good riddance. I wouldn't recommend using the 32-bit version either. (I'm not a fan of MSVC in general; it tends to optimize less well than the other major compilers). – Peter Cordes Aug 21 '17 at 21:36
  • so, how about forgetting about inlining and just write your staff in regular `masm` as a function. looks like you might create a better optimized code this way. – Serge Aug 21 '17 at 21:40
  • 3
    OTOH, I definitely would *not* recommend trying to learn asm in the first place with GNU C inline asm. You have to understand asm *and* GNU C inline-asm constraint syntax to be able to use it correctly, and the using it wrong can be very confusing, because you get weirdness outside the inline-asm block when you modify a register without declaring a clobber. – Peter Cordes Aug 21 '17 at 21:40
  • Are your points really unsigned 16-bit integers? If they're signed, then the `0xFFFF` bit pattern means `-1`, and `10 - (-1)` is 11. Even if they're unsigned, it's not "way too big", only "slightly too big", because the sum of two 32-bit values is only 33 bits. (one 32-bit register + `CF`). If you really need to do 64-bit integer addition, use `add` + `adc`. – Peter Cordes Aug 21 '17 at 21:41
  • `void main()`???? – lost_in_the_source Aug 21 '17 at 23:40
  • @Lorenz - You might also want to consider: [Is inline assembly language slower than native C++ code?](https://stackoverflow.com/questions/9601427/is-inline-assembly-language-slower-than-native-c-code) – Bo Persson Aug 22 '17 at 09:48
  • 1
    @Serge - MSVC supports all [interesting instructions as "intrinsics"](https://learn.microsoft.com/cpp/intrinsics/x64-amd64-intrinsics-list) (similar to the `__builtin_`s in you favorite compiler). That saves us from having to specify input and output registers and clobbering. They are also known by the optimizer which will tune them to the surrounding code, like automatic inlining and reuse values already in registers. What is not supported in 64-bit mode is adding some random asm code in the middle of a function. – Bo Persson Aug 22 '17 at 10:05
  • @EugeneSh.Yeah its a uni ex, I wouldn't put myself trough such a pain as msvc inline asm if I had a choice. – Lorenz Aug 22 '17 at 10:28
  • @stackptr That's the C file I've been given by my uni teacher and the only thing I can modify is the asm :/ – Lorenz Aug 22 '17 at 10:30
  • @PeterCordes Thanks for the tips, also I was wondering that because given a point at (3,10) and the other one at such a huge distance didn't make much sense – Lorenz Aug 22 '17 at 10:35

0 Answers0