main.cpp
#include <stdio.h>
#include <inttypes.h>
#include "../../commonfiles/miscdefs.h"

extern "C" Int64 IntegerAdd(Int64 a, Int64 b, Int64 c, Int64 d, Int64 e, Int64 f);
extern "C" Int64 IntegerMul(Int8 a, Int16 b, Int32 c, Int64 d, Int8 e, Int16 f, Int32 g, Int64 h);
extern "C" void IntegerDiv(Int64 a, Int64 b, Int64 quo_rem_ab[2], Int64 c, Int64 d, Int64 quo_rem_cd[2]);

void IntegerAddCpp(void)
{
    Int64 a = 100;
    Int64 b = 200;
    Int64 c = -300;
    Int64 d = 400;
    Int64 e = -500;
    Int64 f = 600;

    // Calculate a + b + c + d + e + f
    Int64 sum = IntegerAdd(a, b, c, d, e, f);

    printf("\nResults for IntegerAdd\n");
    printf("a: %" PRId64 " b: %" PRId64 " c: %" PRId64 "\n", a, b, c);
    printf("d: %" PRId64 " e: %" PRId64 " f: %" PRId64 "\n", d, e, f);
    printf("sum: %" PRId64 "\n", sum);
}

void IntegerMulCpp(void)
{
    Int8 a = 2;
    Int16 b = -3;
    Int32 c = 8;
    Int64 d = 4;
    Int8 e = 3;
    Int16 f = -7;
    Int32 g = -5;
    Int64 h = 10;

    // Calculate a * b * c * d * e * f * g * h
    Int64 result = IntegerMul(a, b, c, d, e, f, g, h);

    printf("\nResults for IntegerMul\n");  
    printf("a: %" PRId8 " b: %" PRId16 " c: %" PRId32 " d: %" PRId64 "\n", a, b, c, d);
    printf("a: %" PRId8 " b: %" PRId16 " c: %" PRId32 " d: %" PRId64 "\n", e, f, g, h);
    printf("result: %" PRId64 "\n", result);
}

void IntegerDivCpp(void)
{
    Int64 a = 102;
    Int64 b = 7;
    Int64 quo_rem_ab[2];
    Int64 c = 61;
    Int64 d = 9;
    Int64 quo_rem_cd[2];

    // Calculate a / b  and c / d
    IntegerDiv(a, b, quo_rem_ab, c, d, quo_rem_cd);

    printf("\nResults for IntegerDiv\n");
    printf("a:   %" PRId64 " b:   %" PRId64 " ", a, b);
    printf("quo: %" PRId64 " rem: %" PRId64 "\n", quo_rem_ab[0], quo_rem_ab[1]);
    printf("c:   %" PRId64 " d:   %" PRId64 " ", c, d);
    printf("quo: %" PRId64 " rem: %" PRId64 "\n", quo_rem_cd[0], quo_rem_cd[1]);
}

int main(int argc, char* argv[])
{
    IntegerAddCpp();
    IntegerMulCpp();
    IntegerDivCpp();
    return 0;
}
integerarithmetic.asm
; Name:         integerarithmetic.asm
;
; Build:        g++ -c main.cpp -o main.o
;               nasm -f elf64 -o integerarithmetic.o integerarithmetic.asm
;               g++ -o integerarithmetic integerarithmetic.o main.o
;
; Description:  Demonstration of GCC with nasm calling convention on Linux
;               However we can program this example easier, I've followed the
;               Windows Visual Studio way to calculate the results.  Just to show
;               how different things can be.
;
; Source:       Modern x86 Assembly Language Programming p.504

bits 64

global IntegerAdd
global IntegerMul
global IntegerDiv

section .text

; extern "C" Int64 IntegerAdd(Int64 a, Int64 b, Int64 c, Int64 d, Int64 e, Int64 f)
;
; Description:  The following function demonstrates 64-bit integer
;               addition.

IntegerAdd:
    ; Calculate sum of argument values
    add     rdi,rsi          ;rdi = a + b
    add     rcx,rdx          ;rcx = c + d
    mov     rax,r8           ;rax = e
    add     rax,r9           ;rax = e + f
    add     rcx,rdi          ;rcx = a + b + c + d
    add     rax,rcx          ;rax = a + b + c + d + e + f
    ret

; extern "C" Int64 IntegerMul(Int8 a, Int16 b, Int32 c, Int64 d, Int8 e, Int16 f, Int32 g, Int64 h);
;
; Description:  The following function demonstrates 64-bit signed
;               integer multiplication.
; Remark:       Intel stores the negative byte and word values already signed extended in a
;               dword register meaning that we can sign extend a dword immediately. Anyway,
;               in this example we see the use of the 8bit value of di (dil) and r8 (r8b).
;               Users who have the books source code will notice that the stack is used
;               slightly different used than in Windows VC++.  That's because gcc in linux 
;               uses a different ABI.

IntegerMul:
    ; Calculate a * b
    movsx   rdi,dil                     ;dil = a, sign_extend(a) in rdi
    movsx   rsi,si                      ;si = b, sign_extend(b) in rsi
    imul    rdi,rsi                     ;rdi = a * b
    ;Calculate c * d                    ;rcx = d
    movsxd  rdx,edx                     ;edx = c, sign_extend(c) in rdx
    imul    rcx,rdx                     ;rcx = c * d
    ; Calculate e * f
    movsx   r8,r8b                      ;r8b = e, sign_extend(e) in r8
    movsx   r9,r9w                      ;r9w = f, sign_extend(f) in r9
    imul    r8,r9                       ;r8 = e * f
    ; Calculate g * h
    movsxd  rax,dword[rsp+8]            ;rax = sign_extend(g)
    imul    rax,[rsp+16]                ;rax = g * h
    ; Compute final result
    imul    rax,rdi                     ;rax = a * b * g * h
    imul    rax,rcx                     ;rax = a * b * c * d * g * h
    imul    rax,r8                      ;rax = a * b * c * d * e * f * g * h
    ;rax = final product
    ret

; extern "C" void IntegerDiv(Int64 a, Int64 b, Int64 quo_rem_ab[2], Int64 c, Int64 d, Int64 quo_rem_cd[2]);
;
; Description:  The following function demonstrates 64-bit signed
;               integer division.

IntegerDiv:
    mov     r10,rdx                     ;save pointer to quo_rem_ab[2]
    ; Additional we check for division by zero
    cmp     rsi,0
    je      .bzero
    ; Calculate a / b, save quotient and remainder
    mov     rax,rdi                     ;rax = a
    cqo                                 ;rdx:rax = sign_extend(a)
    idiv    rsi                         ;rax = quo a/b, rdx = rem a/b
    jmp     .l1
    .bzero:
    mov     rax,-1                      ;both values -1
    mov     rdx,-1
    .l1:    
    mov     qword[r10],rax              ;save quotient
    mov     qword[r10+8],rdx            ;save remainder
    ; Additional we check for division by zero
    cmp     r8,0
    je      .dzero
    ; Calculate c / d, save quotient and remainder
    mov     rax,rcx                     ;rax = c
    cqo                                 ;rdx:rax is sign_extend(c)
    idiv    r8                          ;rax = quo c/d, rdx = rem c/d
    jmp     .l2
    .dzero:
    mov     rax,-1                      ;both values -1
    mov     rdx,-1
    .l2:
    mov     qword[r9],rax               ;save quotient
    mov     qword[r9+8],rdx             ;save remainder
    ret
build
g++ -c main.cpp -o main.o
nasm -f elf64 -o integerarithmetic.o integerarithmetic.asm
g++ -o integerarithmetic integerarithmetic.o main.o