Author Topic: Int128 in assembler  (Read 1037 times)

bigbadbob

  • Regular Member
  • *
  • Posts: 17
Re: Int128 in assembler
« Reply #30 on: June 15, 2018, 04:26:54 PM »
So I did this in C#:

Code: [Select]
    [StructLayout(LayoutKind.Sequential)]
    public struct Int128
    {
        private Int64 loQWORD;
        private Int64 hiQWORD;

        [DllImport("BigBadInt128.dll")]
        private static extern Int128 Int128Add(ref Int128 addend1, ref Int128 addend2);

        public static Int128 operator+ (Int128 addend1, Int128 addend2)
        {
            return Int128Add(ref addend1, ref addend2);
        }
}

And this in 64-bit assembly:
Code: [Select]
Int128Add PROC
   mov r10, QWORD PTR [rdx]
   mov r11, QWORD PTR [rdx+8]
   add r10, QWORD PTR [r8]
   adc r11, QWORD PTR [r8+8]
   mov QWORD PTR [rcx], r10
   mov QWORD PTR [rcx+8], r11
   mov rax, rcx
   ret 
Int128Add ENDP 

nidud

  • Member
  • *****
  • Posts: 1528
    • https://github.com/nidud/asmc
Re: Int128 in assembler
« Reply #31 on: June 15, 2018, 11:55:18 PM »
You are doing this:
void Int128Add(_m128* const input1, _m128* const input2, _m128* result )

Which is the correct way of doing it.

Quote
while what you really want is this (or some variation on the same line):
_m128 result = Int128Add(_m128* const input1, _m128* const input)
but you don't know yet how to do it.

Unless he uses a more sophisticated compiler this will not be possible given the maximum returned integer value is 64-bit. Using xmm register in this case will be counter productive. It will just add a lot of bloat and reduce the speed of the alogo.

AW

  • Member
  • *****
  • Posts: 1347
  • Let's Make ASM Great Again!
Re: Int128 in assembler
« Reply #32 on: June 16, 2018, 12:26:41 AM »
Come on nidud, you should know this  :redface:

typedef struct
{
   __int64 num1;
   __int64 num2;
}_m128t;

int main()
{
   _m128t in1 = { 1,1 };
   _m128t in2 = { 2,2 };

   _m128t myNum = Int128Add(&in1, &in2);

    return 0;
}

   _m128t myNum = Int128Add(&in1, &in2);
000000013F124D50  lea         r8,[in2] 
000000013F124D54  lea         rdx,[in1] 
000000013F124D58  lea         rcx,[rbp+188h] 
000000013F124D5F  call        Int128Add (013F121375h) 


Look at how RCX is used, lol.

nidud

  • Member
  • *****
  • Posts: 1528
    • https://github.com/nidud/asmc
Re: Int128 in assembler
« Reply #33 on: June 16, 2018, 01:31:32 AM »
 :biggrin:

Your not very clever are are you.

    Int128Add(&a, &b, &result)

        lea rcx,a
        lea rdx,b
        lea r8,result
        call Int128Add

Quote
Look at how RCX is used [now], lol.

A more sophisticated compiler is capable of doing this without using pointers:

    __int128 a = 0x0000000100000001;
    __int128 b = 0x0000000200000002;
    __int128 result = Int128Add(a, b);

AW

  • Member
  • *****
  • Posts: 1347
  • Let's Make ASM Great Again!
Re: Int128 in assembler
« Reply #34 on: June 16, 2018, 01:41:49 AM »
I am talking about Windows ABI since the beginning of this thread and you are talking about a feature of the GCC compiler (a more sophisticated compiler according to you  :icon_eek:)

nidud

  • Member
  • *****
  • Posts: 1528
    • https://github.com/nidud/asmc
Re: Int128 in assembler
« Reply #35 on: June 16, 2018, 01:47:00 AM »
In ASM we have owords but the ABI does not consider them a "returnable" data type.

:biggrin:

None of the functions presented by Bob use any return type other than void and all arguments are passed as pointers.

AW

  • Member
  • *****
  • Posts: 1347
  • Let's Make ASM Great Again!
Re: Int128 in assembler
« Reply #36 on: June 16, 2018, 01:52:05 AM »
I know you will end winning any discussion due to fatigue of the opponent.

I will keep only this for the record:
Quote
Unless he uses a more sophisticated compiler this will not be possible given the maximum returned integer value is 64-bit.
:bgrin:

nidud

  • Member
  • *****
  • Posts: 1528
    • https://github.com/nidud/asmc
Re: Int128 in assembler
« Reply #37 on: June 16, 2018, 01:58:34 AM »
 :biggrin:

As for GCC I mention that so Bob could write the algos in C and convert them to assembly online to test them.

There's nothing wrong with Add function Bob, and the first version also works :t

The C function goes something like this:
Code: [Select]
void Int128Add(__int128 *a, __int128 *b, __int128 *result)
{
    *result = *a + *b;
}

You may copy and past it into https://gcc.godbolt.org/

As for your usual (your all idiots because you don't know what I just learn five minutes ago from google) babble, that's just entertainment.

AW

  • Member
  • *****
  • Posts: 1347
  • Let's Make ASM Great Again!
Re: Int128 in assembler
« Reply #38 on: June 16, 2018, 02:07:10 AM »
As for your usual (your all idiots because you don't know what I just learn five minutes ago from google) babble, that's just entertainment.
You are a bad loser, you should recognize the nonsense you have been saying. This kind of ignorance is not acceptable from someone that is developing an assembler supposed to be compliant with the Windows ABI. Or is it compliant with the GCC ABI?
Bob is saying that he is a C# developer since the first message and you don't stop push selling your GCC ideas.

bigbadbob

  • Regular Member
  • *
  • Posts: 17
Re: Int128 in assembler
« Reply #39 on: June 16, 2018, 11:50:28 AM »
I would like to learn the Windows ABI way of doing it.  I'll be using C# from Windows.  I might also use it from C++, but it will be the Visual Studio compiler.

hutch--

  • Administrator
  • Member
  • ******
  • Posts: 5484
  • Mnemonic Driven API Grinder
    • The MASM32 SDK
Re: Int128 in assembler
« Reply #40 on: June 16, 2018, 12:49:26 PM »
Bob,

Don't take any notice of the "kiddies", its just a form of sport.  :P

Kiddies,

Behave yourself ! ;)
hutch at movsd dot com
http://www.masm32.com    :biggrin:  :biggrin:

nidud

  • Member
  • *****
  • Posts: 1528
    • https://github.com/nidud/asmc
Re: Int128 in assembler
« Reply #41 on: June 16, 2018, 11:11:34 PM »
 :biggrin:

Well, as for behavior:
Quote
You are a bad loser, you should recognize the nonsense you have been saying.

Yes AW, we are all idiots  :P

What I've been saying is that using VS your limited to 64-bit size arguments and return values so you have to use pointers. This means that the add function needs three pointers regardless on how you declare it. The alternate approach in VS will be using xmm registers, but you can't do large integer math using vectors so that will be a rather clunky implementation.

I gain some experience from the REAL16 implementation in Asmc which is similar to what Bob is doing. This also uses __int128 integer math for +-*/ and so on, so that's why I preferred the method Bob initially used. This is also the standard for most Windows API function where input and output are passed as pointers with a boolean return value.

Well, there are many good reasons why you should avoid using nonstandard return values, especially if there's no gain in doing so.

Quote
This kind of ignorance is not acceptable from someone that is developing an assembler supposed to be compliant with the Windows ABI.
I posted a sample using that assembler where 128-bit arguments was converted to 64-bit pointers to illustrate just that.

Quote
Or is it compliant with the GCC ABI?
Yes, both 32 and 64-bit. You can download the Linux version her.

Quote
Bob is saying that he is a C# developer since the first message and you don't stop push selling your GCC ideas.
As already mention, C# is not bound to a specific ABI. It's created to be used on different computer platforms without being rewritten for specific architectures. The same also apply to most compilers, GCC included, which is able to produce binaries from source written in C, pascal, stdcall, fastcall, sycall, vectorcall for both Windows and Linux ABI.

Assembler is the opposite, custom made code for a specific ABI, which forces you to make a choice.

AW

  • Member
  • *****
  • Posts: 1347
  • Let's Make ASM Great Again!
Re: Int128 in assembler
« Reply #42 on: June 16, 2018, 11:29:44 PM »
Quote
What I've been saying is that using VS your limited to 64-bit size arguments and return values so you have to use pointers.
What's wrong with using pointers? We all know that XMM registers are bad doing integer operations, and they don't any 128-bit operation! They are just carriers  :badgrin:, so you will have to offload their content to make something useful. People usually forget that! It is the same with the VectorCall convention, people forget that the XMM registers have to be loaded and this takes CPU cycles. Don't embark in buzz words, experiment and test by yourself.

Quote
bla, bla bla, ...

No comments. You insist that C# has 128-bit data types. It has NOT.

Quote
As already mention, C# is not bound to a specific ABI. It's created to be used on different computer platforms without being rewritten for specific architectures.
Welcome to planet Earth, please land now that there is no fog. Things here are quite different.  :biggrin:

hutch--

  • Administrator
  • Member
  • ******
  • Posts: 5484
  • Mnemonic Driven API Grinder
    • The MASM32 SDK
Re: Int128 in assembler
« Reply #43 on: June 17, 2018, 01:57:49 AM »
 :biggrin:

> What I've been saying is that using VS your limited to 64-bit size arguments and return values so you have to use pointers.

VS does have a technique for writing 128 and 256 bit data types, its called MASM. That is why Microsoft supply MASM in both the old 32 bit version and the 64 bit version. Now you can be sure that nether will run on a Motorola MAC, MIPS, PDP8 or Lunix but both can produce binaries for the OS they are supplied for, Windows.  :P
hutch at movsd dot com
http://www.masm32.com    :biggrin:  :biggrin:

nidud

  • Member
  • *****
  • Posts: 1528
    • https://github.com/nidud/asmc
Re: Int128 in assembler
« Reply #44 on: June 17, 2018, 02:57:05 AM »
What's wrong with using pointers?

Memory access is costly so it would be better to use registers. That's why they come up with things like fastcall, to make it faster and more compact.

Simple test case:

Registers:
Code: [Select]
    mov rax,rcx ; in:  rdx:rcx, r8:r9
    add rax,r8  ; out: rdx:rax
    adc rdx,r9
Pointers:
Code: [Select]
    mov r9,[rcx]        ; in:  [rcx], [rdx]
    mov r10,[rcx+8]     ; out: [r8]
    add r9,[rdx]
    adc r10,[rdx+8]
    mov [r8],r9
    mov [r8+8],r10

Result:
Quote
total [1 .. 3], 1++
   301615 cycles 0.asm: register
   883794 cycles 1.asm: pointers
hit any key to continue...

So that's one of the reasons why people like assembler: it makes faster and less bloated code. There's hundreds (if not thousand) of similar tests in the Lab if you interested in learning to write assembler code. You see, your assertion that it's impossible to write assembler code which is faster and more compact than optimized C++ is simply not true (I assume that was the conclusion in the article you wrote).

Code: [Select]
The benchmark for the C/ASM implementation:

19532 ClockTicks: Asmc  32-bit asmc-lib 342K
21871 ClockTicks: Asmc  64-bit asmc-lib 448K
28392 ClockTicks: JWasm 32-bit watcom   345K
30327 ClockTicks: Uasm  64-bit windows  844K
40466 ClockTicks: Uasm  32-bit windows  723K
49375 ClockTicks: Asmc  64-bit windows  531K

Quote
We all know that XMM registers are bad doing integer operations, and they don't any 128-bit operation! They are just carriers  :badgrin:, so you will have to offload their content to make something useful. People usually forget that!

The Linux implementation of the Quadmath actually use both. There may be some advantages in doing that but I failed to see any:
Quote
The alternate approach in VS will be using xmm registers, but you can't do large integer math using vectors so that will be a rather clunky implementation.

Quote
It is the same with the VectorCall convention, people forget that the XMM registers have to be loaded and this takes CPU cycles. Don't embark in buzz words, experiment and test by yourself.

This is simply not true so I think it's safe to just write this off as pure ignorance on your part.

Quote
No comments. You insist that C# has 128-bit data types. It has NOT.
I did not, but given there are libraries which support this architecture that may be the case. Visual Studio have support for __int128 but since Win64 don't support this it will just flag it off with an error:
Code: [Select]
__int128 foo(__int128 a, __int128 b)
{
    return (a + b);
}
Quote
test.c(2) : error C4235: nonstandard extension used : '__int128' keyword not supported on this architecture

Code: [Select]
__int129 foo(__int129 a, __int129 b)
...
Quote
test.c(2) : error C2061: syntax error : identifier 'foo'
test.c(2) : error C2059: syntax error : ';'
test.c(2) : error C2146: syntax error : missing ')' before identifier 'a'
test.c(2) : error C2061: syntax error : identifier 'a'
test.c(2) : error C2059: syntax error : ','
test.c(2) : error C2059: syntax error : ')'