Thread overview
Calling assembly functions from C++.
Jun 14, 2004
Noob_programmer
Jun 14, 2004
Walter
Jun 15, 2004
Noob_programmer
Jun 15, 2004
Walter
Jun 18, 2004
Noob_programmer
Jun 19, 2004
Walter
Jun 19, 2004
Mark Junker
Jun 19, 2004
Mark Junker
Jun 15, 2004
Noob_programmer
June 14, 2004
I posted this in the 16-bit dos forum a few days ago and haven't recieved a responce yet.  Maybe someone here can help me out.




hi,
I am trying to call an assembly function I made, from a c++ program.  I get an
error message from the DM compiler that states

diag01.obj(diag01)
Error 42: Symbol Undefined _memSize

--- errorlevel 1

I use the command:
dmc diag01.cpp -msd

But it creates an executable that seems to run.

Here is the assembly code:

Public _memSize

data

buffer1 BYTE 20 DUP(?)
count	DWORD 0

code

_memSize PROC NEAR, C
PUSH EBP
MOV EBX, 00000000h
MOV AX, SEG buffer1
MOV ES, AX
MOV AX, OFFSET buffer1
MOV DI, AX
L1:
MOV EAX, 0000E820h
MOV EDX, 534D4150h		;'SMAP'
MOV ECX, SIZEOF buffer1
INT 15h
JC L2
CMP EBX, 0
JZ L2
MOV EAX, OFFSET buffer1 + 8
MOV ECX, [EAX]			;Dereference EAX
ADD count, ECX
JMP L1
L2:
POP EBP
RET
_memSize ENDP

END


And here is the C++ code:

#include <iostream.h>
#include <stdlib.h>

extern "C" void memSize();

int main()
{
unsigned int choice;
unsigned long count = 0;
system ("CLS");
do
{
cout << "Choose something. ";
cin >> choice;
switch(choice)
{
case 1:   system ("CLS");
cout << "Option 1\n";
break;
case 2:   system ("CLS");
cout << "Option 2\n";
memSize();
break;
case 3:   system ("CLS");
cout << "Option 3\n";
break;
case 0:   system ("CLS");
cout << "Exiting!!!\n";
break;
default:  system ("CLS");
cout << "Not a valid selection, please re-choose!\n";
}
}while(choice != 0);
return 0;
}


Could someone please look at my code and tell me what I am doing wrong.

Also, could someone tell me how to return values from the assembly funtion back to the C++ calling program.

Thanks

BTW: The assembly funtion finds the total system memory(conventional, reserved,
and extended).





June 14, 2004
You need to link in the object file that the assembler created.

"Noob_programmer" <Noob_programmer_member@pathlink.com> wrote in message news:caiv7b$1pnn$1@digitaldaemon.com...
> I posted this in the 16-bit dos forum a few days ago and haven't recieved
a
> responce yet.  Maybe someone here can help me out.
>
>
>
>
> hi,
> I am trying to call an assembly function I made, from a c++ program.  I
get an
> error message from the DM compiler that states
>
> diag01.obj(diag01)
> Error 42: Symbol Undefined _memSize
>
> --- errorlevel 1
>
> I use the command:
> dmc diag01.cpp -msd
>
> But it creates an executable that seems to run.
>
> Here is the assembly code:
>
> Public _memSize
>
> data
>
> buffer1 BYTE 20 DUP(?)
> count DWORD 0
>
> code
>
> _memSize PROC NEAR, C
> PUSH EBP
> MOV EBX, 00000000h
> MOV AX, SEG buffer1
> MOV ES, AX
> MOV AX, OFFSET buffer1
> MOV DI, AX
> L1:
> MOV EAX, 0000E820h
> MOV EDX, 534D4150h ;'SMAP'
> MOV ECX, SIZEOF buffer1
> INT 15h
> JC L2
> CMP EBX, 0
> JZ L2
> MOV EAX, OFFSET buffer1 + 8
> MOV ECX, [EAX] ;Dereference EAX
> ADD count, ECX
> JMP L1
> L2:
> POP EBP
> RET
> _memSize ENDP
>
> END
>
>
> And here is the C++ code:
>
> #include <iostream.h>
> #include <stdlib.h>
>
> extern "C" void memSize();
>
> int main()
> {
> unsigned int choice;
> unsigned long count = 0;
> system ("CLS");
> do
> {
> cout << "Choose something. ";
> cin >> choice;
> switch(choice)
> {
> case 1:   system ("CLS");
> cout << "Option 1\n";
> break;
> case 2:   system ("CLS");
> cout << "Option 2\n";
> memSize();
> break;
> case 3:   system ("CLS");
> cout << "Option 3\n";
> break;
> case 0:   system ("CLS");
> cout << "Exiting!!!\n";
> break;
> default:  system ("CLS");
> cout << "Not a valid selection, please re-choose!\n";
> }
> }while(choice != 0);
> return 0;
> }
>
>
> Could someone please look at my code and tell me what I am doing wrong.
>
> Also, could someone tell me how to return values from the assembly funtion
back
> to the C++ calling program.
>
> Thanks
>
> BTW: The assembly funtion finds the total system memory(conventional,
reserved,
> and extended).
>
>
>
>
>


June 15, 2004
It is still doing the same thing, here is the output.

C:\dm\bin>dmc diag01.cpp memSize.obj -msd
diag01.cpp:
link diag01+memSize/noi;
OPTLINK (R) for Win32  Release 7.50B1
Copyright (C) Digital Mars 1989 - 2001  All Rights Reserved

diag01.obj(diag01)
Error 42: Symbol Undefined _memSize

--- errorlevel 1


The linker doesn't seem to be finding it.  Any other suggestions?




In article <caj1ij$1sut$2@digitaldaemon.com>, Walter says...
>
>You need to link in the object file that the assembler created.
>
>"Noob_programmer" <Noob_programmer_member@pathlink.com> wrote in message news:caiv7b$1pnn$1@digitaldaemon.com...
>> I posted this in the 16-bit dos forum a few days ago and haven't recieved
>a
>> responce yet.  Maybe someone here can help me out.
>>
>>
>>
>>
>> hi,
>> I am trying to call an assembly function I made, from a c++ program.  I
>get an
>> error message from the DM compiler that states
>>
>> diag01.obj(diag01)
>> Error 42: Symbol Undefined _memSize
>>
>> --- errorlevel 1
>>
>> I use the command:
>> dmc diag01.cpp -msd
>>
>> But it creates an executable that seems to run.
>>
>> Here is the assembly code:
>>
>> Public _memSize
>>
>> data
>>
>> buffer1 BYTE 20 DUP(?)
>> count DWORD 0
>>
>> code
>>
>> _memSize PROC NEAR, C
>> PUSH EBP
>> MOV EBX, 00000000h
>> MOV AX, SEG buffer1
>> MOV ES, AX
>> MOV AX, OFFSET buffer1
>> MOV DI, AX
>> L1:
>> MOV EAX, 0000E820h
>> MOV EDX, 534D4150h ;'SMAP'
>> MOV ECX, SIZEOF buffer1
>> INT 15h
>> JC L2
>> CMP EBX, 0
>> JZ L2
>> MOV EAX, OFFSET buffer1 + 8
>> MOV ECX, [EAX] ;Dereference EAX
>> ADD count, ECX
>> JMP L1
>> L2:
>> POP EBP
>> RET
>> _memSize ENDP
>>
>> END
>>
>>
>> And here is the C++ code:
>>
>> #include <iostream.h>
>> #include <stdlib.h>
>>
>> extern "C" void memSize();
>>
>> int main()
>> {
>> unsigned int choice;
>> unsigned long count = 0;
>> system ("CLS");
>> do
>> {
>> cout << "Choose something. ";
>> cin >> choice;
>> switch(choice)
>> {
>> case 1:   system ("CLS");
>> cout << "Option 1\n";
>> break;
>> case 2:   system ("CLS");
>> cout << "Option 2\n";
>> memSize();
>> break;
>> case 3:   system ("CLS");
>> cout << "Option 3\n";
>> break;
>> case 0:   system ("CLS");
>> cout << "Exiting!!!\n";
>> break;
>> default:  system ("CLS");
>> cout << "Not a valid selection, please re-choose!\n";
>> }
>> }while(choice != 0);
>> return 0;
>> }
>>
>>
>> Could someone please look at my code and tell me what I am doing wrong.
>>
>> Also, could someone tell me how to return values from the assembly funtion
>back
>> to the C++ calling program.
>>
>> Thanks
>>
>> BTW: The assembly funtion finds the total system memory(conventional,
>reserved,
>> and extended).
>>
>>
>>
>>
>>
>
>


June 15, 2004
It is still doing the same thing, here is the output.

C:\dm\bin>dmc diag01.cpp memSize.obj -msd
diag01.cpp:
link diag01+memSize/noi;
OPTLINK (R) for Win32  Release 7.50B1
Copyright (C) Digital Mars 1989 - 2001  All Rights Reserved

diag01.obj(diag01)
Error 42: Symbol Undefined _memSize

--- errorlevel 1


The linker doesn't seem to be finding it.  Any other suggestions?




In article <caj1ij$1sut$2@digitaldaemon.com>, Walter says...
>
>You need to link in the object file that the assembler created.
>
>"Noob_programmer" <Noob_programmer_member@pathlink.com> wrote in message news:caiv7b$1pnn$1@digitaldaemon.com...
>> I posted this in the 16-bit dos forum a few days ago and haven't recieved
>a
>> responce yet.  Maybe someone here can help me out.
>>
>>
>>
>>
>> hi,
>> I am trying to call an assembly function I made, from a c++ program.  I
>get an
>> error message from the DM compiler that states
>>
>> diag01.obj(diag01)
>> Error 42: Symbol Undefined _memSize
>>
>> --- errorlevel 1
>>
>> I use the command:
>> dmc diag01.cpp -msd
>>
>> But it creates an executable that seems to run.
>>
>> Here is the assembly code:
>>
>> Public _memSize
>>
>> data
>>
>> buffer1 BYTE 20 DUP(?)
>> count DWORD 0
>>
>> code
>>
>> _memSize PROC NEAR, C
>> PUSH EBP
>> MOV EBX, 00000000h
>> MOV AX, SEG buffer1
>> MOV ES, AX
>> MOV AX, OFFSET buffer1
>> MOV DI, AX
>> L1:
>> MOV EAX, 0000E820h
>> MOV EDX, 534D4150h ;'SMAP'
>> MOV ECX, SIZEOF buffer1
>> INT 15h
>> JC L2
>> CMP EBX, 0
>> JZ L2
>> MOV EAX, OFFSET buffer1 + 8
>> MOV ECX, [EAX] ;Dereference EAX
>> ADD count, ECX
>> JMP L1
>> L2:
>> POP EBP
>> RET
>> _memSize ENDP
>>
>> END
>>
>>
>> And here is the C++ code:
>>
>> #include <iostream.h>
>> #include <stdlib.h>
>>
>> extern "C" void memSize();
>>
>> int main()
>> {
>> unsigned int choice;
>> unsigned long count = 0;
>> system ("CLS");
>> do
>> {
>> cout << "Choose something. ";
>> cin >> choice;
>> switch(choice)
>> {
>> case 1:   system ("CLS");
>> cout << "Option 1\n";
>> break;
>> case 2:   system ("CLS");
>> cout << "Option 2\n";
>> memSize();
>> break;
>> case 3:   system ("CLS");
>> cout << "Option 3\n";
>> break;
>> case 0:   system ("CLS");
>> cout << "Exiting!!!\n";
>> break;
>> default:  system ("CLS");
>> cout << "Not a valid selection, please re-choose!\n";
>> }
>> }while(choice != 0);
>> return 0;
>> }
>>
>>
>> Could someone please look at my code and tell me what I am doing wrong.
>>
>> Also, could someone tell me how to return values from the assembly funtion
>back
>> to the C++ calling program.
>>
>> Thanks
>>
>> BTW: The assembly funtion finds the total system memory(conventional,
>reserved,
>> and extended).
>>
>>
>>
>>
>>
>
>


June 15, 2004
"Noob_programmer" <Noob_programmer_member@pathlink.com> wrote in message news:cana79$2lnv$1@digitaldaemon.com...
> It is still doing the same thing, here is the output.
>
> C:\dm\bin>dmc diag01.cpp memSize.obj -msd
> diag01.cpp:
> link diag01+memSize/noi;
> OPTLINK (R) for Win32  Release 7.50B1
> Copyright (C) Digital Mars 1989 - 2001  All Rights Reserved
>
> diag01.obj(diag01)
> Error 42: Symbol Undefined _memSize
>
> --- errorlevel 1
>
>
> The linker doesn't seem to be finding it.  Any other suggestions?

Run obj2asm on your memSize.obj and have a look to see if _memSize is in it.


June 18, 2004
I was talking to a friend and he told me that MASM provides the _'s during assembly and that they are un-neccessary in the source code.  So I followed his suggestion and low and behold it worked.

I am encountering another problem as well now.  I am writing a program in C++
using the Digital Mars compiler that calls a procedure I wrote in assembly.  The
procedure totals the total memory size(conventional, reserved, and extended),
places the total in EAX and returns to the C++ calling program.
When I run the procedure seperatly, it works fine.  When I run the C++ program
that calls the procedure, it diesn't work.
This is the command I throw the DM compiler

> dmc diag01.cpp memSize.asm -msd

This is the updated assembly code:

PUBLIC memSize
MODEL SMALL, C
386

data

buffer1 BYTE 20 DUP(?)
count	DWORD 0

code

memSize PROC NEAR
PUSH EBP
MOV EBX, 00000000h
MOV AX, SEG buffer1
MOV ES, AX
MOV AX, OFFSET buffer1
MOV DI, AX

L1:

MOV EAX, 0000E820h
MOV EDX, 534D4150h		;'SMAP'
MOV ECX, SIZEOF buffer1
INT 15h
JC L2
CMP EBX, 0
JZ L2
MOV EAX, OFFSET buffer1 + 8
MOV ECX, [EAX]
ADD count, ECX
JMP L1

L2:

MOV EAX, count
POP EBP
RET
memSize ENDP

END

This is the C++ code:

#include <iostream.h>
#include <stdlib.h>

extern "C" void memSize();

int main()
{
unsigned int choice;
unsigned long count = 0;
system ("CLS");
do
{
cout << "Choose something. ";
cin >> choice;
switch(choice)
{
case 1:   system ("CLS");
cout << "Option 1\n";
break;
case 2:   system ("CLS");
cout << "Option 2\n";
memSize();
_asm
{
MOV count, EAX
}
cout << count << endl;
break;
case 3:   system ("CLS");
cout << "Option 3\n";
break;
case 0:   system ("CLS");
cout << "Exiting!!!\n";
break;
default:  system ("CLS");
cout << "Not a valid selection, please re-choose!\n";
}
}while(choice != 0);
return 0;
}


When I run the program, it outputs 0.  0 is the original value I initalize count with in the beginning of the assembly code(I tested to see if the code modifies the value by placing different values in count and the program outputs the value I place in it).  This is telling me that the assembly code isn't modifing the value.

If anyone can give me any suggestions, I would appreiciate it.  I am starting to go CRAZY!!!!!





In article <canegb$2s9j$2@digitaldaemon.com>, Walter says...
>
>
>"Noob_programmer" <Noob_programmer_member@pathlink.com> wrote in message news:cana79$2lnv$1@digitaldaemon.com...
>> It is still doing the same thing, here is the output.
>>
>> C:\dm\bin>dmc diag01.cpp memSize.obj -msd
>> diag01.cpp:
>> link diag01+memSize/noi;
>> OPTLINK (R) for Win32  Release 7.50B1
>> Copyright (C) Digital Mars 1989 - 2001  All Rights Reserved
>>
>> diag01.obj(diag01)
>> Error 42: Symbol Undefined _memSize
>>
>> --- errorlevel 1
>>
>>
>> The linker doesn't seem to be finding it.  Any other suggestions?
>
>Run obj2asm on your memSize.obj and have a look to see if _memSize is in it.
>
>


June 19, 2004
A couple things. First, you can just do:
    count = memSize();
Second, when you can't figure out why a program isn't working, simplify,
simplify, simplify. For example, rewrite memSize() so it is just a:
    mov EAX,3
    ret
and get that to work. Iostreams is very complex. You don't need it in a
simplified program, it just confuses things, use printf instead.
Third, there seems to be some confusion as to whether your program is a 16
bit one or a 32 bit one, i.e. the code mixes and matches 16 and 32 bit
addressing modes.
Lastly, obj2asm is your friend. I can't emphasize this enough. Obj2asm both
modules and go through the assembler listing of your simplified, simplified,
SIMPLIFIED code.

"Noob_programmer" <Noob_programmer_member@pathlink.com> wrote in message news:cauufa$1ug8$1@digitaldaemon.com...
> I was talking to a friend and he told me that MASM provides the _'s during assembly and that they are un-neccessary in the source code.  So I
followed his
> suggestion and low and behold it worked.
>
> I am encountering another problem as well now.  I am writing a program in
C++
> using the Digital Mars compiler that calls a procedure I wrote in
assembly.  The
> procedure totals the total memory size(conventional, reserved, and
extended),
> places the total in EAX and returns to the C++ calling program.
> When I run the procedure seperatly, it works fine.  When I run the C++
program
> that calls the procedure, it diesn't work.
> This is the command I throw the DM compiler
>
> > dmc diag01.cpp memSize.asm -msd
>
> This is the updated assembly code:
>
> PUBLIC memSize
> MODEL SMALL, C
> 386
>
> data
>
> buffer1 BYTE 20 DUP(?)
> count DWORD 0
>
> code
>
> memSize PROC NEAR
> PUSH EBP
> MOV EBX, 00000000h
> MOV AX, SEG buffer1
> MOV ES, AX
> MOV AX, OFFSET buffer1
> MOV DI, AX
>
> L1:
>
> MOV EAX, 0000E820h
> MOV EDX, 534D4150h ;'SMAP'
> MOV ECX, SIZEOF buffer1
> INT 15h
> JC L2
> CMP EBX, 0
> JZ L2
> MOV EAX, OFFSET buffer1 + 8
> MOV ECX, [EAX]
> ADD count, ECX
> JMP L1
>
> L2:
>
> MOV EAX, count
> POP EBP
> RET
> memSize ENDP
>
> END
>
> This is the C++ code:
>
> #include <iostream.h>
> #include <stdlib.h>
>
> extern "C" void memSize();
>
> int main()
> {
> unsigned int choice;
> unsigned long count = 0;
> system ("CLS");
> do
> {
> cout << "Choose something. ";
> cin >> choice;
> switch(choice)
> {
> case 1:   system ("CLS");
> cout << "Option 1\n";
> break;
> case 2:   system ("CLS");
> cout << "Option 2\n";
> memSize();
> _asm
> {
> MOV count, EAX
> }
> cout << count << endl;
> break;
> case 3:   system ("CLS");
> cout << "Option 3\n";
> break;
> case 0:   system ("CLS");
> cout << "Exiting!!!\n";
> break;
> default:  system ("CLS");
> cout << "Not a valid selection, please re-choose!\n";
> }
> }while(choice != 0);
> return 0;
> }
>
>
> When I run the program, it outputs 0.  0 is the original value I initalize
count
> with in the beginning of the assembly code(I tested to see if the code
modifies
> the value by placing different values in count and the program outputs the
value
> I place in it).  This is telling me that the assembly code isn't modifing
the
> value.
>
> If anyone can give me any suggestions, I would appreiciate it.  I am
starting to
> go CRAZY!!!!!
>
>
>
>
>
> In article <canegb$2s9j$2@digitaldaemon.com>, Walter says...
> >
> >
> >"Noob_programmer" <Noob_programmer_member@pathlink.com> wrote in message news:cana79$2lnv$1@digitaldaemon.com...
> >> It is still doing the same thing, here is the output.
> >>
> >> C:\dm\bin>dmc diag01.cpp memSize.obj -msd
> >> diag01.cpp:
> >> link diag01+memSize/noi;
> >> OPTLINK (R) for Win32  Release 7.50B1
> >> Copyright (C) Digital Mars 1989 - 2001  All Rights Reserved
> >>
> >> diag01.obj(diag01)
> >> Error 42: Symbol Undefined _memSize
> >>
> >> --- errorlevel 1
> >>
> >>
> >> The linker doesn't seem to be finding it.  Any other suggestions?
> >
> >Run obj2asm on your memSize.obj and have a look to see if _memSize is in
it.
> >
> >
>
>


June 19, 2004
Noob_programmer schrieb:

> I was talking to a friend and he told me that MASM provides the _'s during
> assembly and that they are un-neccessary in the source code.  So I followed his
> suggestion and low and behold it worked.

Thats the defined behaviour when you use the function language specifier "C".

> I am encountering another problem as well now.  I am writing a program in C++
> using the Digital Mars compiler that calls a procedure I wrote in assembly.  The
> procedure totals the total memory size(conventional, reserved, and extended),
> places the total in EAX and returns to the C++ calling program.  When I run the procedure seperatly, it works fine.  When I run the C++ program
> that calls the procedure, it diesn't work.
> This is the command I throw the DM compiler
> 
> 
>>dmc diag01.cpp memSize.asm -msd
> 
> 
> This is the updated assembly code:
> 
> PUBLIC memSize
> MODEL SMALL, C
> 386
> 
> data
> 
> buffer1 BYTE 20 DUP(?)
> count	DWORD 0
> 
> code
> 
> memSize PROC NEAR PUSH EBP
> MOV EBX, 00000000h
> MOV AX, SEG buffer1
> MOV ES, AX

Please save ES before using it.

> MOV AX, OFFSET buffer1
> MOV DI, AX

Please save DI before using it.

> 
> L1:
> 
> MOV EAX, 0000E820h
> MOV EDX, 534D4150h		;'SMAP'
> MOV ECX, SIZEOF buffer1		
> INT 15h
> JC L2
> CMP EBX, 0

test ebx, ebx

> JZ L2

> MOV EAX, OFFSET buffer1 + 8
> MOV ECX, [EAX]			

Change the two lines above to:
mov ecx, es:[di + 8]

> ADD count, ECX
> JMP L1
> 
> L2:
> 
> MOV EAX, count

Please return output in DX:AX, because ... -> see comment in c++ source.

> POP EBP
> RET	
> memSize ENDP
> 
> END
> 
> This is the C++ code:
> 
> #include <iostream.h>
> #include <stdlib.h>
> 
> extern "C" void memSize();

Specify as: extern "C" long memSize(void);

> 
> int main()
> {
> unsigned int choice;
> unsigned long count = 0;
> system ("CLS");
> do
> {
> cout << "Choose something. ";
> cin >> choice;
> switch(choice)
> {
> case 1:   system ("CLS");
> cout << "Option 1\n";
> break;
> case 2:   system ("CLS");
> cout << "Option 2\n";
> memSize();
> _asm
> {
> MOV count, EAX
> }

Don't use inline assembler at this point because you cannot know how many assembler instructions will be inserted by the compiler between the function call and the inline assembler block.

> cout << count << endl;
> break;
> case 3:   system ("CLS");
> cout << "Option 3\n";
> break;
> case 0:   system ("CLS");
> cout << "Exiting!!!\n";
> break;
> default:  system ("CLS");
> cout << "Not a valid selection, please re-choose!\n";
> }
> }while(choice != 0);
> return 0;
> }
> 
> 
> When I run the program, it outputs 0.  0 is the original value I initalize count
> with in the beginning of the assembly code(I tested to see if the code modifies
> the value by placing different values in count and the program outputs the value
> I place in it).  This is telling me that the assembly code isn't modifing the
> value.  
> 
> If anyone can give me any suggestions, I would appreiciate it.  I am starting to
> go CRAZY!!!!!

Is this function really supported by your BIOS?

Maybe you can try another function to find out how many memory is installed in your system ...


Anyway, below is my memSize function. Might be usefull for you.
Compile with: dmc -3 -msd test.cpp

#pragma pack(push,1)
struct TMemoryMap {
    unsigned long ulBaseLo, ulBaseHi;
    unsigned long ulLengthLo, ulLengthHi;
    unsigned long ulType;
};
#pragma pack(pop)

extern "C"
static
long memSize(void)
{
    unsigned long ulSize = 0;
    TMemoryMap Buffer;

    bool bDidFail;
    long lNextValue = 0;
    do {
        int iFlags = 0;
        long lEAX = 0, lEBX = 0;
        __asm {
            mov ebx, lNextValue

            push di
            push es

            push ss
            pop es
            lea di, Buffer

            mov eax, 0xE820
            mov edx, 0x534d4150
            mov ecx, sizeof(Buffer)
            int 0x15
            pop es
            pop di

            pushf
            pop iFlags
            mov lEAX, eax
            mov lEBX, ebx
        }

	// print INT function status information
        printf("%04x, %08lx, %08lx\n", iFlags, lEAX, lEBX);

	// check for CF && EAX=="SMAP"
        bDidFail = (iFlags & 1) || (lEAX!=0x534d4150);
        if (!bDidFail) {
            ulSize += Buffer.ulLengthLo;
            lNextValue = lEBX;  // continuation value
        }

	// print more status information
        printf("%d / %08lx / %08lx\n", (int) bDidFail, ulSize, lNextValue);
    } while (!bDidFail && lNextValue!=0);

    return ulSize;
}

Regards,
Mark
June 19, 2004
Noob_programmer schrieb:

> I was talking to a friend and he told me that MASM provides the _'s during
> assembly and that they are un-neccessary in the source code.  So I followed his
> suggestion and low and behold it worked.

Thats the defined behaviour when you use the function language specifier "C".

> I am encountering another problem as well now.  I am writing a program in C++
> using the Digital Mars compiler that calls a procedure I wrote in assembly.  The
> procedure totals the total memory size(conventional, reserved, and extended),
> places the total in EAX and returns to the C++ calling program.  When I run the procedure seperatly, it works fine.  When I run the C++ program
> that calls the procedure, it diesn't work.
> This is the command I throw the DM compiler
> 
> 
>>dmc diag01.cpp memSize.asm -msd
> 
> 
> This is the updated assembly code:
> 
> PUBLIC memSize
> MODEL SMALL, C
> 386
> 
> data
> 
> buffer1 BYTE 20 DUP(?)
> count	DWORD 0
> 
> code
> 
> memSize PROC NEAR PUSH EBP
> MOV EBX, 00000000h
> MOV AX, SEG buffer1
> MOV ES, AX

Please save ES before using it.

> MOV AX, OFFSET buffer1
> MOV DI, AX

Please save DI before using it.

> 
> L1:
> 
> MOV EAX, 0000E820h
> MOV EDX, 534D4150h		;'SMAP'
> MOV ECX, SIZEOF buffer1		
> INT 15h
> JC L2
> CMP EBX, 0

test ebx, ebx

> JZ L2

> MOV EAX, OFFSET buffer1 + 8
> MOV ECX, [EAX]			

Change the two lines above to:
mov ecx, es:[di + 8]

> ADD count, ECX
> JMP L1
> 
> L2:
> 
> MOV EAX, count

Please return output in DX:AX, because ... -> see comment in c++ source.

> POP EBP
> RET	
> memSize ENDP
> 
> END
> 
> This is the C++ code:
> 
> #include <iostream.h>
> #include <stdlib.h>
> 
> extern "C" void memSize();

Specify as: extern "C" long memSize(void);

> 
> int main()
> {
> unsigned int choice;
> unsigned long count = 0;
> system ("CLS");
> do
> {
> cout << "Choose something. ";
> cin >> choice;
> switch(choice)
> {
> case 1:   system ("CLS");
> cout << "Option 1\n";
> break;
> case 2:   system ("CLS");
> cout << "Option 2\n";
> memSize();
> _asm
> {
> MOV count, EAX
> }

Don't use inline assembler at this point because you cannot know how many assembler instructions will be inserted by the compiler between the function call and the inline assembler block.

> cout << count << endl;
> break;
> case 3:   system ("CLS");
> cout << "Option 3\n";
> break;
> case 0:   system ("CLS");
> cout << "Exiting!!!\n";
> break;
> default:  system ("CLS");
> cout << "Not a valid selection, please re-choose!\n";
> }
> }while(choice != 0);
> return 0;
> }
> 
> 
> When I run the program, it outputs 0.  0 is the original value I initalize count
> with in the beginning of the assembly code(I tested to see if the code modifies
> the value by placing different values in count and the program outputs the value
> I place in it).  This is telling me that the assembly code isn't modifing the
> value.  
> 
> If anyone can give me any suggestions, I would appreiciate it.  I am starting to
> go CRAZY!!!!!

Is this function really supported by your BIOS?

Maybe you can try another function to find out how many memory is installed in your system ...


Anyway, below is my memSize function. Might be usefull for you.
Compile with: dmc -3 -msd test.cpp

#pragma pack(push,1)
struct TMemoryMap {
    unsigned long ulBaseLo, ulBaseHi;
    unsigned long ulLengthLo, ulLengthHi;
    unsigned long ulType;
};
#pragma pack(pop)

extern "C"
long memSize(void)
{
    unsigned long ulSize = 0;
    TMemoryMap Buffer;

    bool bDidFail;
    long lNextValue = 0;
    do {
        int iFlags = 0;
        long lEAX = 0, lEBX = 0;
        __asm {
            mov ebx, lNextValue

            push di
            push es

            push ss
            pop es
            lea di, Buffer

            mov eax, 0xE820
            mov edx, 0x534d4150
            mov ecx, sizeof(Buffer)
            int 0x15
            pop es
            pop di

            pushf
            pop iFlags
            mov lEAX, eax
            mov lEBX, ebx
        }

	// print INT function status information
        printf("%04x, %08lx, %08lx\n", iFlags, lEAX, lEBX);

	// check for CF && EAX=="SMAP"
        bDidFail = (iFlags & 1) || (lEAX!=0x534d4150);
        if (!bDidFail) {
            ulSize += Buffer.ulLengthLo;
            lNextValue = lEBX;  // continuation value
        }

	// print more status information
        printf("%d / %08lx / %08lx\n", (int) bDidFail, ulSize, lNextValue);
    } while (!bDidFail && lNextValue!=0);

    return ulSize;
}

Regards,
Mark