News:

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

Main Menu

Progress ?

Started by hutch--, July 09, 2016, 10:03:11 PM

Previous topic - Next topic

hutch--

Working away, finding out bits and pieces. You can construct include files in a simpler way than Vasily has done using this format.

extern ActivateActCtx:PROC
extern AddAtomA:PROC
extern AddAtomW:PROC
extern AddConsoleAliasA:PROC
extern AddConsoleAliasW:PROC
extern AddLocalAlternateComputerNameA:PROC
extern AddLocalAlternateComputerNameW:PROC
extern AddRefActCtx:PROC
extern AddVectoredContinueHandler:PROC
extern AddVectoredExceptionHandler:PROC
extern AllocConsole:PROC
etc .....

I have found a quirk with the size of the object modules that ML64 produces. If you include a number large header files you end up with a massive object module and while it does not effect the final executable size, it is a problem for creating libraries. The solution is a pain but may be necessary, only include the "extern funcname:PROC" that you need and the size remains small. You can find the IMPORTS by using "dumpbin.exe" if the object module has a lot of API calls in it.

Console mode is trivial to get up and going, have StdOut and ErrOut working and have the start of a 64 bit library. Rationalised the macros used so far but only need enough to continue testing at the moment.

qWord

The problem is EXTERN that always creates entries in the object file.
Replacing EXTERN with EXTERNDEF leads to the wished behavior.
MREAL macros - when you need floating point arithmetic while assembling!

Vortex

It's possible to automate the creation of include files. My scanner tool looks for the invoke statements and generates the required include files.

Here is Vasily's window example.

Build.bat

scan Window.asm -m -o:window.inc

\masm64\bin\ml64.exe /c window.asm

\masm64\bin\link.exe /SUBSYSTEM:WINDOWS /ENTRY:WinMain /LARGEADDRESSAWARE window.obj

pause


window.inc

extern ExitProcess:PROC
extern CreateWindowExA:PROC
CreateWindowEx EQU <CreateWindowExA>
extern DefWindowProcA:PROC
DefWindowProc EQU <DefWindowProcA>
extern DispatchMessageA:PROC
DispatchMessage EQU <DispatchMessageA>
extern GetMessageA:PROC
GetMessage EQU <GetMessageA>
extern PostQuitMessage:PROC
extern RegisterClassExA:PROC
RegisterClassEx EQU <RegisterClassExA>
extern TranslateMessage:PROC


windows.asm

OPTION DOTNAME
option casemap:none
include \masm64\include\temphls.inc ;* The symbol pair ;* means than scan.exe skips
include \masm64\include\win64.inc   ;* this file

include window.inc

COMMENT @
invoke DefWindowProc
@

includelib \masm64\lib\kernel32.lib
includelib \masm64\lib\user32.lib
.
.
.



mineiro

I have posted this sample as an answer to fearless.
Source code included and command line too.
I'd rather be this ambulant metamorphosis than to have that old opinion about everything

hutch--

qWord,

Thanks for that, changed the two test include files from extern to externdef and the object files dropped to normal size.

As long as there is a clean well defined way to get the list of names in each library, automation of viable include files is possible and about all that needs to be done after the list is equates for either ANSI or UNICODE which can be a conditional either/or. I have made the two test include files (kernel32 & user32) with "dumpbin.exe" and done some minor formatting to get the list into the correct form but there may be a more convenient way to get the lists directly from the libraries.

LATER: I just renamed the extern to externdef in Vasily's user32 and kernel32 include files and it worked fine and automating that will be much easier.

jj2007

I always thought "progress" was when the assembler learnt to use invoke instead of pushpushcall ::)

(M$ is just installing 119 important and 11 less important improvements of Windows 7; that is "progress", too)

hutch--

 :biggrin:

> I always thought "progress" was when the assembler learnt to use invoke instead of pushpushcall

How about, rcx, rdx, r8, r9 then stack calls ?

I think that structure calls are probably a good idea when you need to pass many more arguments rather than on the stack.

LOCAL yst:YOURSTRUCT
; write arguments to structure members
lea rcx, yst
call yourfunction


jj2007

Quote from: hutch-- on July 11, 2016, 12:10:25 PM
:biggrin:

> I always thought "progress" was when the assembler learnt to use invoke instead of pushpushcall

How about, rcx, rdx, r8, r9 then stack calls ?

You missed the point. I meant common situations like this one:include \masm32\include\masm32rt.inc

.code
ToUPPER proc uses esi edi pTextLowerCase, pTitle
Local buffer[1000]:BYTE
  lea edi, buffer
  mov esi, pTextLowerCase
  push edi
  .Repeat
lodsb
.if al>="A" && al<="Z"
or al, 32
.endif
stosb
  .Until !al
  lea edi, buffer
  push MB_YESNOCANCEL
  push edi
  push pTitle
  push 0
  call MessageBox
  ret
ToUPPER endp
start:
  push chr$("THIS IS AN UPPERCASE TEXT")
  push chr$("Conversion to uppercase example:")
  call ToUPPER
  push chr$("You have a bug now, my friend...")
  push chr$("Now that was cute, right?")
  call ToUPPER
  exit

end start

hutch--

Something like this ?


; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

szUpper proc

  ; rcx = address of string

    .stack

    mov rax, rcx
    sub rax, 1

  @@:
    add rax, 1
    cmp BYTE PTR [rax], 0
    je @F
    cmp BYTE PTR [rax], "a"
    jb @B
    cmp BYTE PTR [rax], "z"
    ja @B
    sub BYTE PTR [rax], 32
    jmp @B
  @@:

    mov rax, rcx

    ret

szUpper endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

jj2007

The good ol' times?

Quote from: hutch-- on July 11, 2016, 06:28:48 PM
here is a 1k windows coded the old way, something like the code style of 1990. No equates, mindless label names

Damn, I can't find that post where somebody whose nick starts with "hu" explains that assembly was almost dead until people discovered the advantages of modern stuff like invoke, .Repeat ... .Until, .if /.else/ .endif etc ::)

rrr314159

Quote from: hutch-- on July 11, 2016, 12:10:25 PM
I think that structure calls are probably a good idea when you need to pass many more arguments rather than on the stack.

Yes, I use structures a lot for that. The "ASSUME" command comes in handy for this purpose, you just point rcx at that structure.
I am NaN ;)

jj2007

Instead of ASSUME, you can also use an equate like e.g. Now:  print "Current time: "
  invapi GetLocalTime, offset stime
  if use64
PermReg equ rsi
  else
PermReg equ esi
  endif
  push PermReg
  mov PermReg, offset stime
  Now equ [PermReg.SYSTEMTIME]
  print str$(Now.wHour)
  print ":"
  print str$(Now.wMinute)
  print ":"
  print str$(Now.wSecond)
  pop PermReg
  print chr$(13, 10)


Current time: 19:46:15

rrr314159

For one thing if you want to use the same code for 32 and 64, in a "master" include file write something like this:

if use64
  else
        eax equ rax
        ....
        esi equ rsi
        ...
  endif

Then just use rax, rbx, rsi etc as if it were 64-bit code. For instance in this snippet you would just write "PermReg equ rsi". if use64 is not set, it will use esi instead.

Anyway, of course you can do "Now equ [PermReg.SYSTEMTIME]", but it's clumsier compared to ASSUME. I don't really remember all the little gotcha's. It's been more than a year since I hassled with ML64. As long as you're only doing it in one little routine, as you show here, it's fine, but if using it more extensively (for an important structure, throughout the whole program) there are problems.

Well, I could recommend you glance through my old code to see some of these techniques. When I was learning, I extensively read your code, qWord's, and everyone else's: it's a great way to shorten the learning curve. But you're not going to do that. Clearly you guys will have to go through the whole process yourselves, make the same mistakes, re-invent the wheel, and undoubtedly wind up (after a few months) using H/JWasm like the rest of us. Have fun!

[EDIT] I mean you could learn a few things about 64-bit, especially making the same code compatible with 32 and 64, from my old code. When it comes to overall assembler programming, of course you and hutch know a lot more than I do, don't mean to imply otherwise.
I am NaN ;)

jj2007

Quote from: rrr314159 on July 13, 2016, 08:35:49 AMjust use rax, rbx, rsi etc as if it were 64-bit code.

ife use64
        rax equ eax
        ...
        rsi equ esi
        ...
endif


And that works because an assembler parsing 32-bit code doesn't know the symbol rax. Brilliant idea :t

(I disagree about equates vs assume, though, but that's a matter of taste and readability  ;))

rrr314159

Thanks, in fact I thought of it myself but found out later Japheth had been using that trick for years. As for equate vs. assume someday I'll remember the problems involved. At least I thought there were situations where the equate method was clearly worse, could have been wrong about it.
I am NaN ;)