News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

HJWasm 2.28 release

Started by johnsa, April 21, 2017, 10:39:37 PM

Previous topic - Next topic

johnsa

Hi,

Update available on the site and Git.

Changes:

1) (Just for AW27 ;) ) Added Delphi 32bit fastcall as a language type, so you can use PROC DELPHI etc..
2) Improved linux System V invoke.
3) Renamed some OO stuff in the macro library to avoid conflicts (documentation updated)
4) Added a new option for OPTION PROC:  .. it can now take the following:



OPTION PROC:NONE
OPTION PROC:DEFAULT
OPTION PROC:MyPrologue,MyEpilogue



Which do what you'd expect, the first two are just short-hands to switch off/on the prologue epilogue via option prologue, option epilogue and same goes for the 3rd form which just allows you to specify both macros in one go.

Cheers,
John

aw27

Quote from: johnsa on April 21, 2017, 10:39:37 PM
1) (Just for AW27 ;) ) Added Delphi 32bit fastcall as a language type, so you can use PROC DELPHI etc..

That is very nice!  :t

I found an important small problem, registers edx and ecx are swapped.


.686
.XMM

    .MODEL FLAT, DELPHI
    option casemap:none
.code

proc1 proc public Val1:dword, Val2:dword, Val3:dword, Val4:dword
mov eax, Val1
add eax, Val2
add eax, Val3
add eax, Val4
ret
proc1 endp

end

COMMENT ?

procedure TForm4.btGoClick(Sender: TObject);
var
    retValue : integer;
begin
      retValue:=proc1(2,3,4,5);
end;

testDelphiCall.pas.36: retValue:=proc1(2,3,4,5);
005CBC18 6A05             push $05
005CBC1A B904000000       mov ecx,$00000004
005CBC1F BA03000000       mov edx,$00000003
005CBC24 B802000000       mov eax,$00000002
005CBC29 E812000000       call proc1

proc1:
005CBC40 55               push ebp
005CBC41 8BEC             mov ebp,esp
005CBC43 8BC0             mov eax,eax
005CBC45 03C1             add eax,ecx ; should be add eax, edx
005CBC47 03C2             add eax,edx ; should be add eax, ecx
005CBC49 034508           add eax,[ebp+$08]
005CBC4C 5D               pop ebp
005CBC4D C3               ret

?





johnsa

Will fix/update shortly ! :)

johnsa

Packages and git updated, please try again.

Thanks!
John

jj2007

Perfect for my sources, John :t

Speed has increased a bit, especially for the 64-bit version, which is now only 10% slower than AsmC.

If I had one wish free, it would be a console print flush after each module of a library has finished. Both ML 6.15 and AsmC do it that way - kind of a progress indicator. HJWasm starts assembling and remains silent for two seconds, then suddenly throws out all results in one go. Probably just a matter of taste, though.

aw27

"Under the register convention, up to three parameters are passed in CPU registers, and the rest (if any) are passed on the stack. The parameters are passed in order of declaration (as with the pascal convention), and the first three parameters that qualify are passed in the EAX, EDX, and ECX registers, in that order. Real, method-pointer, variant, Int64, and structured types do not qualify as register parameters, but all other parameters do. If more than three parameters qualify as register parameters, the first three are passed in EAX, EDX, and ECX, and the remaining parameters are pushed onto the stack in order of declaration."

So, when I have a function in Delphi declared like this:
function proc2(val1:single; val2:integer; val3:integer; val4:integer):single; register; external;

As is now, in ASM I would have to declare it like this:
proc2 proc public Val2:dword, Val3:dword, Val4:dword, Val1:real4
and not like this:
proc2 proc public Val1:real4, Val2:dword, Val3:dword, Val4:dword
because the compiler does not see Val1 does not qualify to come in a register.


johnsa

Quote from: jj2007 on April 22, 2017, 01:57:13 AM
Perfect for my sources, John :t

Speed has increased a bit, especially for the 64-bit version, which is now only 10% slower than AsmC.

If I had one wish free, it would be a console print flush after each module of a library has finished. Both ML 6.15 and AsmC do it that way - kind of a progress indicator. HJWasm starts assembling and remains silent for two seconds, then suddenly throws out all results in one go. Probably just a matter of taste, though.

So we should flush output after each processed file, IE: on returning from an included source file, flush any console output relating to that file then continue ?

nidud

#8
deleted

jj2007

Quote from: johnsa on April 22, 2017, 04:54:07 AMSo we should flush output after each processed file, IE: on returning from an included source file, flush any console output relating to that file then continue ?

Yes, that is the idea. Not relevant for single file assembly, but when you have 30 modules, it just flows better. Switching the behaviour with a commandline option (-flush) would be fine, too. Don't invest real time, though, it's really minor cosmetics ;-)

habran

Here is a simple example with DELPHI, tell me where is somthing wrong:
Quote
.386
.model flat,DELPHI
option casemap:none

.data
myreal REAL4 1.2
source db 'delphi is crappy',0
.data?
destiny db 64 dup(0)
.code

CopyString PROC public  USES ebx cnt:DWORD,dest:DWORD,src:DWORD,num:DWORD
    mov ebx,num
@@:
    movzx   ebx,BYTE PTR [ecx+eax]
    mov     BYTE PTR [edx+eax],bl
    sub     eax,1
    jns     @b
    ret
CopyString  ENDP

proc2 proc public  Val1:real4, Val2:real4, Val3:dword, Val4:dword
   mov eax, Val1
   add eax, Val2
   add eax, Val3
   add eax, Val4
   ret
proc2 endp

WinMainCRTStartup proc uses EBX
local bob:DWORD
    invoke proc2 ,myreal, 1.2, 3, 4
    mov bob,15
    invoke CopyString,bob,OFFSET destiny,OFFSET source,bob
    ret
WinMainCRTStartup endp
END


     1: .386
     2: .model flat,DELPHI
     3: option casemap:none
     4:
     5: .data
     6: myreal REAL4 1.2
     7: source db 'delphi is crappy',0
     8: .data?
     9: destiny db 64 dup(0)
    10: .code
    11:
    12: CopyString PROC public  USES ebx cnt:DWORD,dest:DWORD,src:DWORD,num:DWORD
00ED1024 55                   push        ebp 
00ED1025 8B EC                mov         ebp,esp 
00ED1027 53                   push        ebx 
    13:     mov ebx,num
00ED1028 8B 5D 08             mov         ebx,dword ptr [num] 
    14: @@:
    15:     movzx   ebx,BYTE PTR [ecx+eax]
00ED102B 0F B6 1C 08          movzx       ebx,byte ptr [eax+ecx] 
    16:     mov     BYTE PTR [edx+eax],bl
00ED102F 88 1C 10             mov         byte ptr [eax+edx],bl 
    17:     sub     eax,1
00ED1032 83 E8 01             sub         eax,1 
    18:     jns     @b
00ED1035 79 F4                jns         CopyString+7h (0ED102Bh) 
    19:     ret
00ED1037 5B                   pop         ebx 
00ED1038 C9                   leave 
00ED1039 C3                   ret 
    20: CopyString  ENDP
    21:
    22: proc2 proc public  Val1:real4, Val2:real4, Val3:dword, Val4:dword
00ED103A 55                   push        ebp 
00ED103B 8B EC                mov         ebp,esp 
    23: mov eax, Val1
00ED103D 8B C0                mov         eax,eax 
    24: add eax, Val2
00ED103F 03 C2                add         eax,edx 
    25: add eax, Val3
00ED1041 03 C1                add         eax,ecx 
    26: add eax, Val4
00ED1043 03 45 08             add         eax,dword ptr [Val4] 
    27: ret
00ED1046 C9                   leave 
00ED1047 C3                   ret 
    28: proc2 endp
    29:
    30: WinMainCRTStartup proc uses EBX
00ED1048 55                   push        ebp 
00ED1049 8B EC                mov         ebp,esp 
00ED104B 83 EC 04             sub         esp,4 
00ED104E 53                   push        ebx 
    31: local bob:DWORD
    32:     invoke proc2 ,myreal, 1.2, 3, 4
00ED104F A1 00 40 ED 00       mov         eax,dword ptr ds:[00ED4000h] 
00ED1054 BA 9A 99 99 3F       mov         edx,3F99999Ah 
00ED1059 B9 03 00 00 00       mov         ecx,3 
00ED105E 6A 04                push        4 
00ED1060 E8 D5 FF FF FF       call        proc2 (0ED103Ah) 
    33:     mov bob,15
00ED1065 C7 45 FC 0F 00 00 00 mov         dword ptr [bob],0Fh 
    34:     invoke CopyString,bob,OFFSET destiny,OFFSET source,bob
00ED106C 8B 45 FC             mov         eax,dword ptr [bob] 
00ED106F BA 14 41 ED 00       mov         edx,0ED4114h 
00ED1074 B9 04 40 ED 00       mov         ecx,0ED4004h 
00ED1079 FF 75 FC             push        dword ptr [bob] 
    34:     invoke CopyString,bob,OFFSET destiny,OFFSET source,bob
00ED107C E8 A3 FF FF FF       call        CopyString (0ED1024h) 
    35:     ret
00ED1081 5B                   pop         ebx 
00ED1082 C9                   leave 
00ED1083 C3                   ret 
Cod-Father

aw27

#11
Quote from: habran on April 22, 2017, 06:14:07 AM
Here is a simple example with DELPHI, tell me where is somthing wrong:

It is wrong, Delphi calls like this:
push dword ptr [ebp-$10] ; in your demo change to "push dword ptr [00ED4000h]"
push $3f99999a
mov edx,$00000004
mov eax,$00000003
call proc2

Your code wants to send reals in CPU registers. In CPU registers you can only send dwords, words, bytes, or their signed equivalents and pointers (except pointers to class methods (functions), called method pointers).

Most of the other data types default to be sent by reference - so you receive a pointer to them, which can be placed in a CPU register as well. However, reals and big integers (int64, uint64) are always pushed on the stack (unless you force them to be sent them by reference).

So watch for reals and big integers and you shall be good.




jj2007

Quote from: aw27 on April 22, 2017, 03:35:18 PMIn CPU registers you can only send dwords, words, bytes, or their signed equivalents and pointers

This is assembler, not C 8)
include \Masm32\MasmBasic\Res\JBasic.inc ; ## console demo, builds in 32- or 64-bit mode with ML, AsmC, JWasm, HJWasm ##
.code
usedeb=1
MyInt DQ 1234567812345678
MyR4 REAL4 1234.567
MyR8 REAL8 123456789.123456789

Demo proc <cb> arg1:REAL4, arg2:REAL8, arg3:QWORD
  deb 4, "received:", arg1, arg2, arg3
ret
Demo endp

Init ; OPT_64 1 ; put 0 for 32 bit, 1 for 64 bit assembly
  PrintLine Chr$("This code was assembled with ", @AsmUsed$(1), " in ", jbit$, "-bit format")
  jinvoke Demo, MyR4, MyR8, MyInt
  mov eax, MyR4
  mov rdx, MyR8
  mov rcx, MyInt
  jinvoke Demo, eax, rdx, rcx
  Inkey "OK?"
EndOfCode


Output:This code was assembled with ml64 in 64-bit format
received:
arg1    1234.567016602
arg2    123456789.123456790
arg3    1234567812345678
received:
arg1    1234.567016602
arg2    123456789.123456790
arg3    1234567812345678

aw27

Quote from: jj2007 on April 22, 2017, 06:18:37 PM
Quote from: aw27 on April 22, 2017, 03:35:18 PMIn CPU registers you can only send dwords, words, bytes, or their signed equivalents and pointers

This is assembler, not C 8)
include \Masm32\MasmBasic\Res\JBasic.inc ; ## console demo, builds in 32- or 64-bit mode with ML, AsmC, JWasm, HJWasm ##
.code
usedeb=1
MyInt DQ 1234567812345678
MyR4 REAL4 1234.567
MyR8 REAL8 123456789.123456789

Demo proc <cb> arg1:REAL4, arg2:REAL8, arg3:QWORD
  deb 4, "received:", arg1, arg2, arg3
ret
Demo endp

Init ; OPT_64 1 ; put 0 for 32 bit, 1 for 64 bit assembly
  PrintLine Chr$("This code was assembled with ", @AsmUsed$(1), " in ", jbit$, "-bit format")
  jinvoke Demo, MyR4, MyR8, MyInt
  mov eax, MyR4
  mov rdx, MyR8
  mov rcx, MyInt
  jinvoke Demo, eax, rdx, rcx
  Inkey "OK?"
EndOfCode


Output:This code was assembled with ml64 in 64-bit format
received:
arg1    1234.567016602
arg2    123456789.123456790
arg3    1234567812345678
received:
arg1    1234.567016602
arg2    123456789.123456790
arg3    1234567812345678


I know, what I mean is that in the Delphi API they are not sent.
I don't remember any API (Intel chips) that sends or receives floats in general purpose registers, but my memory fails many times.

habran

Thanks JJ for support :biggrin:

aw27, this looks perfectly legal and natural as well as faster then pushing on the stack:
Quote
    32:     invoke proc2 ,myreal, 1.2, 3, 4
00ED104F A1 00 40 ED 00       mov         eax,dword ptr ds:[00ED4000h] 
00ED1054 BA 9A 99 99 3F       mov         edx,3F99999Ah 
00ED1059 B9 03 00 00 00       mov         ecx,3 
00ED105E 6A 04                     push        4 
00ED1060 E8 D5 FF FF FF        call        proc2 (0ED103Ah)

however, if you insist we can make it the way as it is done in embarcadero delphi, even though that will require much more work.
It'll also require some more time to be done.
Cod-Father