Author Topic: Calling R Language from Asm  (Read 433 times)

LiaoMi

  • Member
  • *****
  • Posts: 1038
Calling R Language from Asm
« on: July 10, 2022, 09:54:59 AM »
Hi :biggrin:,

Rf_initEmbeddedR in Windows - https://stat.ethz.ch/pipermail/r-help/2005-September/079531.html
Download R-4.2.1 for Windows - https://cran.r-project.org/bin/windows/base/ or https://cran.r-project.org/bin/windows/base/R-4.2.1-win.exe
How to Install a Package in R (example included) - https://datatofish.com/install-package-r/
Documentation for package ‘stats’ version 4.3.0 - https://stat.ethz.ch/R-manual/R-devel/library/stats/html/00Index.html

The following libraries are required to run the program: R.dll, Rblas.dll, Rgraphapp.dll, Riconv.dll

Translation of header files and translation into assembler listing is expected soon  :tongue:

Code: [Select]
; void __fastcall R_add1(int alen, int *a)
                public R_add1
R_add1          proc near

arg_0           = dword ptr  8
arg_8           = qword ptr  10h
arg_10          = qword ptr  18h

                mov     [rsp+arg_8], rbx ; $LN13
                mov     [rsp+arg_10], rsi
                push    rdi
                sub     rsp, 20h
                movsxd  rbx, ecx
                mov     rsi, rdx
                mov     rdx, rbx
                mov     ecx, 0Dh
                call    Rf_allocVector
                mov     rcx, rax
                mov     rdi, rax
                call    Rf_protect
                mov     rcx, rdi
                lea     rbx, ds:0[rbx*4]
                call    INTEGER
                mov     rcx, rax        ; void *
                mov     r8, rbx         ; Size
                mov     rdx, rsi        ; Src
                call    memcpy
                lea     rcx, `string'   ; "add1"
                call    Rf_install
                mov     rcx, rax
                mov     rdx, rdi
                call    Rf_lang2
                mov     rcx, rax
                mov     rbx, rax
                call    Rf_protect
                mov     rdx, cs:__imp_R_GlobalEnv
                lea     r8, [rsp+28h+arg_0]
                mov     rcx, rbx
                mov     rdx, [rdx]
                call    R_tryEval
                cmp     [rsp+28h+arg_0], 0
                mov     rsi, rax
                jnz     short loc_F8
                lea     rcx, `string'   ; "R returned: "
                call    printf
                mov     rcx, rsi
                call    REAL
                mov     rcx, rsi
                mov     rbx, rax
                xor     edi, edi
                call    LENGTH
                test    eax, eax
                jle     short loc_EF
                nop     dword ptr [rax+00h]
                nop     word ptr [rax+rax+00000000h]

loc_C8:
                movsd   xmm1, qword ptr [rbx]
                lea     rcx, `string'   ; "%0.1f, "
                movq    rdx, xmm1
                call    printf
                mov     rcx, rsi
                lea     rbx, [rbx+8]
                inc     edi
                call    LENGTH
                cmp     edi, eax
                jl      short loc_C8

loc_EF:
                lea     rcx, `string'   ; "\n"
                jmp     short loc_FF
; ---------------------------------------------------------------------------

loc_F8:
                lea     rcx, `string'   ; "Error occurred calling R\n"

loc_FF:
                call    printf
                mov     ecx, 2
                call    Rf_unprotect
                mov     rbx, [rsp+28h+arg_8]
                mov     rsi, [rsp+28h+arg_10]
                add     rsp, 20h
                pop     rdi
                retn
R_add1          endp

; ---------------------------------------------------------------------------
algn_11E:
                align 20h
_text$mn        ends


; int __fastcall mainCRTStartup(int argc, char **argv)
                public mainCRTStartup
mainCRTStartup  proc near

var_28          = qword ptr -28h
var_20          = qword ptr -20h
var_18          = xmmword ptr -18h
arg_0           = qword ptr  8
arg_8           = qword ptr  10h
arg_10          = dword ptr  18h

                mov     [rsp+arg_8], rbx ; $LN17
                push    rsi
                sub     rsp, 40h
                lea     rax, `string'

loc_131:
                movaps  [rsp+48h+var_18], xmm6
                mov     [rsp+48h+var_28], rax
                lea     rdx, [rsp+48h+var_28]
                lea     rax, `string'   ; "--silent"
                mov     ecx, 2
                mov     [rsp+48h+var_20], rax
                call    Rf_initEmbeddedR
                movdqa  xmm6, cs:__xmm@00000004000000030000000200000001
                lea     rcx, `string'   ; "func.R"
                call    Rf_mkString
                lea     rcx, `string'   ; "source"
                mov     rbx, rax
                call    Rf_install
                mov     rcx, rax
                mov     rdx, rbx
                call    Rf_lang2
                mov     rcx, rax
                mov     rbx, rax
                call    Rf_protect
                mov     rdx, cs:__imp_R_GlobalEnv
                xor     r8d, r8d
                mov     rcx, rbx
                mov     rdx, [rdx]
                call    R_tryEval
                mov     ecx, 1
                call    Rf_unprotect
                mov     edx, 5
                lea     ecx, [rdx+8]
                call    Rf_allocVector
                mov     rcx, rax
                mov     rbx, rax
                call    Rf_protect
                mov     rcx, rbx
                call    INTEGER
                lea     rcx, `string'   ; "add1"
                movups  xmmword ptr [rax], xmm6
                mov     dword ptr [rax+10h], 5
                call    Rf_install
                mov     rcx, rax
                mov     rdx, rbx
                call    Rf_lang2
                mov     rcx, rax
                mov     rbx, rax
                call    Rf_protect
                mov     rdx, cs:__imp_R_GlobalEnv
                lea     r8, [rsp+48h+arg_10]
                mov     rcx, rbx
                mov     rdx, [rdx]
                call    R_tryEval
                cmp     [rsp+48h+arg_10], 0
                mov     rsi, rax
                movaps  xmm6, [rsp+48h+var_18]
                jnz     short loc_285

loc_220:
                lea     rcx, `string'   ; "R returned: "

loc_227:
                mov     [rsp+48h+arg_0], rdi
                call    printf
                mov     rcx, rsi
                call    REAL
                mov     rcx, rsi
                mov     rbx, rax
                xor     edi, edi
                call    LENGTH
                test    eax, eax
                jle     short loc_277
                nop     word ptr [rax+rax+00h]

loc_250:
                movsd   xmm1, qword ptr [rbx]
                lea     rcx, `string'   ; "%0.1f, "
                movq    rdx, xmm1
                call    printf
                mov     rcx, rsi
                lea     rbx, [rbx+8]
                inc     edi
                call    LENGTH
                cmp     edi, eax
                jl      short loc_250

loc_277:
                mov     rdi, [rsp+48h+arg_0]
                lea     rcx, `string'   ; "\n"
                jmp     short loc_28C
; ---------------------------------------------------------------------------

loc_285:
                lea     rcx, `string'   ; "Error occurred calling R\n"

loc_28C:
                call    printf
                mov     ecx, 2
                call    Rf_unprotect
                xor     ecx, ecx
                call    Rf_endEmbeddedR
                mov     rbx, [rsp+48h+arg_8]
                xor     eax, eax
                add     rsp, 40h
                pop     rsi
                retn
mainCRTStartup  endp

; ---------------------------------------------------------------------------
algn_2AF:
                align 10h
_text$mn        ends

; void __fastcall source(const char *name)
                public source
source          proc near
                push    rbx             ; $LN4
                sub     rsp, 20h
                call    Rf_mkString
                lea     rcx, `string'   ; "source"
                mov     rbx, rax
                call    Rf_install
                mov     rcx, rax
                mov     rdx, rbx
                call    Rf_lang2
                mov     rcx, rax
                mov     rbx, rax
                call    Rf_protect
                mov     rdx, cs:__imp_R_GlobalEnv
                xor     r8d, r8d
                mov     rcx, rbx
                mov     rdx, [rdx]
                call    R_tryEval
                mov     ecx, 1
                add     rsp, 20h
                pop     rbx
                jmp     Rf_unprotect
source          endp

; ---------------------------------------------------------------------------
algn_304:
                align 8
_text$mn        ends

C++
Code: [Select]
void source(const char *name)
{
    SEXP e;

    PROTECT(e = lang2(install("source"), mkString(name)));
    R_tryEval(e, R_GlobalEnv, NULL);
    UNPROTECT(1);
}

/**
 * Wrapper for R function add1, defined in func.R.
 */
void R_add1(int alen, int a[])
{
    // Allocate an R vector and copy the C array into it.
    SEXP arg;
    PROTECT(arg = allocVector(INTSXP, alen));
    memcpy(INTEGER(arg), a, alen * sizeof(int));

    // Setup a call to the R function
    SEXP add1_call;
    PROTECT(add1_call = lang2(install("add1"), arg));

    // Execute the function
    int errorOccurred;
    SEXP ret = R_tryEval(add1_call, R_GlobalEnv, &errorOccurred);

    if (!errorOccurred)
    {
        printf("R returned: ");
        double *val = REAL(ret);
        for (int i = 0; i < LENGTH(ret); i++)
            printf("%0.1f, ", val[i]);
        printf("\n");
    }
    else
    {
        printf("Error occurred calling R\n");
    }
   
    UNPROTECT(2);
}

int mainCRTStartup(int argc, char *argv[])
{
    // Intialize the R environment.
    int r_argc = 2;
    char *r_argv[] = { "R", "--silent" };
    Rf_initEmbeddedR(r_argc, r_argv);
   
    int arg[] = { 1, 2, 3, 4, 5 };

    // Invoke a function in R
    source("func.R");
    R_add1(5, arg);

    // Release R environment
    Rf_endEmbeddedR(0);
    return(0);
}

R Func
Code: [Select]
# This function is invoked by the C program r_test

add1 <- function(a) {
  cat("R received: ", a, "\n");

  return(a + 1)
}

HSE

  • Member
  • *****
  • Posts: 2252
  • AMD 7-32 / i3 10-64
Re: Calling R Language from Asm
« Reply #1 on: July 10, 2022, 11:22:47 PM »
Hi LiaoMi!

I have that idea in 2017. But R.dll have 4 MB and there is frequents updates.

Also R console is very complete and you can run scripts (from elementals to very complex).

Finally I maked assembly programs that write hard calculations results to files that can be read by R scripts.

Regards, HSE.
Equations in Assembly: SmplMath