### Author Topic: Length Error when calling DLL from high level language  (Read 2493 times)

#### markB

• Regular Member
• Posts: 7
##### Re: Length Error when calling DLL from high level language
« Reply #15 on: June 25, 2017, 12:09:44 PM »
Thanks very much for your reply.  Because a deadline is fast approaching, I had to re-write this differently, and now it runs and serves my needs in this case.

I'll come back to this thread later, but I want to thank everybody who answered my question -- you all posted very helpful information.

#### AW

• Member
• Posts: 1355
• Let's Make ASM Great Again!
##### Re: Length Error when calling DLL from high level language
« Reply #16 on: June 25, 2017, 05:07:44 PM »
Thanks very much for your reply.  Because a deadline is fast approaching, I had to re-write this differently, and now it runs and serves my needs in this case.

That's a cool idea to rewrite it from scratch, particularly because nobody uses "USES EBP" in this World.
In spite of that, the apparent cause for the error was that you can not index arrays in MASM as you do in any other language. In MASM you must take into account the size of the element itself (in MASM they call it TYPE, so the confusion starts just here).

As an illustration:

Code: [Select]
`.686.model Flat, Stdcalloption Casemap :None  includelib h:\masm32\lib\msvcrt.lib ; (*)printf PROTO C :VARARG Counter=0.dataformat db "%d",13,10,0someStruct STRUCTREPEAT 1024 Counter = Counter + 1 dword CounterENDMsomeStruct ENDSmyStruct someStruct <>.codeTM460_Pvtx_Values_Sub1 Proc USES ebx edi Last20EBands1:PTR DWord mov edi, Last20EBands1 xor ebx, ebx .while ebx<sizeof(someStruct)/TYPE(DWORD) mov edx, dword ptr [edi+ebx*TYPE(DWORD)] INVOKE printf, offset format, edx inc ebx .endw retTM460_Pvtx_Values_Sub1 endpmain PROC INVOKE TM460_Pvtx_Values_Sub1, offset myStruct retmain ENDPEND main`
(*) Replace as needed. Someone may tell that you should use  \masm32\lib\msvcrt.lib because relative addresses work all the time. Of course, they do not when you scatter things all over the place,
Build with:
"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\ml" /c /coff test.asm
"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\link" /SUBSYSTEM:console test.obj
« Last Edit: June 26, 2017, 06:28:47 PM by aw27 »

#### coder

• Member
• Posts: 103
##### Re: Length Error when calling DLL from high level language
« Reply #17 on: June 25, 2017, 08:37:46 PM »
I have written a DLL in MASM to call from a high-level language.  The proc assembles correctly and the DLL is created and placed in the proper directory.

When I call this DLL, I get the following error:  Length Error.

Here is the PROC header for the MASM code.  It returns a pointer to the variable BlueLineConfig.

_____

TM460_Pvtx_Values_Sub1 Proc USES ebp Last20EBands1:PTR DWord

mov ebp,Last20EBands1
BlueLineConfig dd 4 dup (0)
mov edi,OFFSET BlueLineConfig

mov eax,DWORD PTR[ebp+114]
mov ebx,DWORD PTR[ebp+108]

[remaining code]

* * *
mov eax,[edi]

RET

TM460_Pvtx_Values_Sub1 EndP

end LibMain
_____

This Proc takes only one input, an array of 140 elements, in DWord form.  I can't see why I would get a Length Error when I am passing exactly what I specified.

Thanks very much for any help.

I don't understand what your code does, but my initial guess is that you do not fully understand how the real, low-level codes of a "proc" works. For example, EBP is a taboo register once high-level proc is involved, especially when you have both local variables and function arguments in the function. Look;

Code: [Select]
`push ebpmov ebp,esppush ebp                  ;your attempt to save EBPsub esp,12mov eax,[ebp+8]                    ;first argumentmov ebp,something_elsemov dword ptr[ebp-8],'ABC'   ;local variable. Now EBP is corrupt due to previous linemov ebx,[ebp+12]                  ; second argument also has corrupt EBP. `
So while you think you have saved the EBP, the truth is, your "proc" uses it internally.

#### jj2007

• Member
• Posts: 8516
• Assembler is fun ;-)
##### Re: Length Error when calling DLL from high level language
« Reply #18 on: June 25, 2017, 08:45:50 PM »
my initial guess is that you do not fully understand how the real, low-level codes of a "proc" works.

@Mark: Ignore this, it's wrong. Test it:
Code: [Select]
`include \masm32\include\masm32rt.inc.codeMyTest proc uses esi edi ebx ebp hwnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORDLOCAL MyLocVar:DWORD  print str\$(hwnd), 9, "hwnd", 13, 10  print str\$(uMsg), 9, "uMsg", 13, 10  print str\$(wParam), 9, "wParam", 13, 10  print str\$(lParam), 9, "lParam", 13, 10  retMyTest endpstart:  invoke MyTest, 11111, 22222, 33333, 44444  inkey "ok?"  exitend start`
It is quite unusual to save ebp but the code would work. Your problem is elsewhere, probably in the way you call the DLL from Python.

#### AW

• Member
• Posts: 1355
• Let's Make ASM Great Again!
##### Re: Length Error when calling DLL from high level language
« Reply #19 on: June 25, 2017, 09:32:53 PM »
It is quite unusual to save ebp but the code would work. Your problem is elsewhere, probably in the way you call the DLL from Python.
Jochen,
In his particular case works simply because he loads only once a variable from the stack to the ebp register. mov ebp, [ebp+8]. In general it would not work when you use ebp as the frame base pointer.

#### hutch--

• Administrator
• Member
• Posts: 5483
• Mnemonic Driven API Grinder
##### Re: Length Error when calling DLL from high level language
« Reply #20 on: June 25, 2017, 09:52:38 PM »
The general idea would be to fix all of the register usage first, put it into a conventional procedure with a stack frame and make sure you properly observe the Intel "Application Binary Interface" for Win32. If you don't do this you get unexpected crashes as the OS expects certain registers not to be changed between procedure calls. Nor is it sensible to just experiment with one OS version because there is no garrantee that it will be the same in another version. The only safe way is to properly observe the previously mentioned ABI. I would imagine that Python properly observes the Intel ABI so you should be safe in doing the same.

Get it up and going reliably and if there is some need, you can do things like removing the stack frame to reduce the call overhead but be aware that this only matters on very short procedures, on longer ones and ones that call other procedures it is a waste of time.
hutch at movsd dot com
http://www.masm32.com

#### jj2007

• Member
• Posts: 8516
• Assembler is fun ;-)
##### Re: Length Error when calling DLL from high level language
« Reply #21 on: June 25, 2017, 09:59:04 PM »
Jochen,
In his particular case works simply because he loads only once a variable from the stack to the ebp register. mov ebp, [ebp+8]. In general it would not work when you use ebp as the frame base pointer.

Right: You cannot use ebp as a variable and use local variables. But the usage of ebp as such does no harm as long as you don't use any locals and/or arguments.

I posted here a Python script using a simple DLL. It's messy, to say the least. Python does strange things with strings under the hood

However, Mark's problem seems very easy to solve - exchanging ebp with ebx (or esi, edi) should be sufficient. The mechanism of passing arguments as such works perfectly.

#### AW

• Member
• Posts: 1355
• Let's Make ASM Great Again!
##### Re: Length Error when calling DLL from high level language
« Reply #22 on: June 25, 2017, 11:38:47 PM »
I posted here a Python script using a simple DLL. It's messy, to say the least. Python does strange things with strings under the hood
Teachers and people from universities are so proficient in Python, Perl and eventually F (and some in Javascript as well, grrrr) that I don' t dare to argue with them about the virtues of other stuff.

#### nidud

• Member
• Posts: 1527
##### Re: Length Error when calling DLL from high level language
« Reply #23 on: June 26, 2017, 12:08:26 AM »
Right: You cannot use ebp as a variable and use local variables.

Code: [Select]
`    .486    .model flat, coption dllimport:<msvcrt>printf proto :ptr byte, :varargexit   proto :dwordoption stackbase:esp    .codefoo proc uses ebp a1, a2local l1,l2    mov ebp,a1    mov l1,ebp    mov ebp,a2    mov l2,ebp    mov ebp,l1    add ebp,l2    mov eax,ebp    retfoo endpmain proc        printf("1 + 2 = %d\n", foo(1, 2))    exit(0)main endp    end main`

#### jj2007

• Member
• Posts: 8516
• Assembler is fun ;-)
##### Re: Length Error when calling DLL from high level language
« Reply #24 on: June 26, 2017, 12:19:46 AM »
Error A2210: Syntax error: printf

#### coder

• Member
• Posts: 103
##### Re: Length Error when calling DLL from high level language
« Reply #25 on: June 26, 2017, 12:28:24 AM »
my initial guess is that you do not fully understand how the real, low-level codes of a "proc" works.

@Mark: Ignore this, it's wrong. Test it:
Code: [Select]
`include \masm32\include\masm32rt.inc.codeMyTest proc uses esi edi ebx ebp hwnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORDLOCAL MyLocVar:DWORD  print str\$(hwnd), 9, "hwnd", 13, 10  print str\$(uMsg), 9, "uMsg", 13, 10  print str\$(wParam), 9, "wParam", 13, 10  print str\$(lParam), 9, "lParam", 13, 10  retMyTest endpstart:  invoke MyTest, 11111, 22222, 33333, 44444  inkey "ok?"  exitend start`
It is quite unusual to save ebp but the code would work. Your problem is elsewhere, probably in the way you call the DLL from Python.

JJ

I don't quite follow which part of my advice is wrong. EBP is a base pointer register, extremely common in stack programming. I thought you knew...

#### jj2007

• Member
• Posts: 8516
• Assembler is fun ;-)
##### Re: Length Error when calling DLL from high level language
« Reply #26 on: June 26, 2017, 12:39:33 AM »
I thought you knew...

Yes I know.

#### hutch--

• Administrator
• Member
• Posts: 5483
• Mnemonic Driven API Grinder
##### Re: Length Error when calling DLL from high level language
« Reply #27 on: June 26, 2017, 01:24:31 AM »
Something I have done in the past is copy arguments to registers from the EBP based addresses then push EBP, use it then pop it but it is risky stuff. You can also do old trick from the win3 days of DLLs and store registers in global variables and while its not elegant, it does work OK.
hutch at movsd dot com
http://www.masm32.com