So there's a new NetRun feature available today, "Link With:". The deal is you just type in the name of some saved routine into the "Link With:" box, and that routine gets linked into the routine you're running. For now, you can only link two routines together, but if you call the linker yourself outside NetRun, you can link as many separate files as you want.
Try it out on my tiny multi-precision arithmetic class by first grabbing this assembly code, then run it with this C++ code.
;void assembly_add_mp(dest,src1,src2)(executable NetRun link)
;Do a multi-precision addition of these two source numbers into dest.
; Stack:
; src2
; src1
; dest
; return address
global assembly_add_mp ; <- makes subroutine visible from outside
assembly_add_mp:
mov esi,[esp+4]; dest, destination array
mov edi,[esp+8]; src1
mov edx,[esp+12]; src2
mov ecx,1; i, Loop counter
mov ax,0
push ax ; Zero out status flags
START_O_LOOP:
; Restore status flags
pop ax
SAHF
mov eax,[edi+4*ecx]; src1[i]
adc eax,[edx+4*ecx]; src2[i]
mov [esi+4*ecx],eax; dest[i]
; Save cursed flags
LAHF
push ax
inc ecx; i++
cmp ecx,[edi+0]; i<=length of arrays
jle START_O_LOOP
pop ax; Clean up stack
ret
C++ "mangles" the linker names of its functions to include the data types of the function arguments. This is good, because it lets you overload function names; but it's bad, because plain C and assembly don't do anything special to the linker names of functions.
In C or assembly, a function "foo" shows up as just plain "foo" in the linker. In C++, a function foo shows up as "foo()" or "foo(int,double,void *)". (Check out the disassembly to be sure how your linker names are coming out.)
So if you call C or assembly code from C++, you have to turn off C++'s name mangling by declaring the C or assembly routines 'extern "C"', like this:
extern "C" void some_assembly_routine(int param1,char *param2);or wrapped in curly braces like this:
extern "C" {
void one_assembly_routine(int x);
void another_assembly_routine(char c);
}
In fact, it's common to provide a "magic" header file for C code that automatically provides 'extern "C"' prototypes for C++, but just works normally in plain C:
#ifdef __cplusplus /* only defined in C++ code */Definitely try these things out yourself:
extern "C" {
#endif
void one_assembly_routine(int x);
void another_assembly_routine(char c);
#ifdef __cplusplus /* only defined in C++ code */
}
#endif
int bar(int i,int j) {(executable NetRun link)
printf("bar(%d,%d)\n",i,j);
return i;
}
extern "C" int bar(int i,int j);(executable NetRun link)
int foo(void)
{
return bar(2,3);
}
Code written in |
With name |
Has linker name |
C++ |
int bar(int a,int b) |
bar(int,int) <- But "mangled" to be alphanumeric... |
C++ |
extern "C" int bar(int a,int b) | bar |
C |
int bar(int a,int b) |
bar |
Assembly |
global bar bar: |
bar |
Fortran |
SUBROUTINE bar() |
bar_, BAR, BAR_, bar__, or some such. Disassemble to be sure... |