News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Macro Question

Started by FORTRANS, March 24, 2024, 07:43:51 AM

Previous topic - Next topic

FORTRANS

Hi,

   I decided to convert a 16-bit DOS program into a Windows
version.  I am not very familiar with INVOKE and have essen-
tially used copy and paste from the MSAM32 examples, and some
other programs from members of the forum, to write my earlier
programs.  So I tried to convert a MACRO to avoid rewriting
around 400 macro calls.  I am proceeding slowly, so any help
is welcome.

   Here is the first attempt.  As yet untested.  Do you see
any problems to be fixed or improvements that can be made?

        PAGE 53,132

;   Does this look okay?

IF 1

; Windows version to write to a console.

@PutText MACRO @Col, @Row, @Attr, @Msg, @Len    ; Msg's and Len's could be
        MOV     [Row],1
        MOV     [Col],23
        MOV     AX,[Row]
        SHL     EAX,16
        MOV     AX,[Col]
        INVOKE  SetConsoleCursorPosition, [MyOutH], EAX
;       INVOKE  SetConsoleTextAttribute, [MyOutH], FOREGROUND_BLUE OR FOREGROUND_INTENSITY
        INVOKE  SetConsoleTextAttribute, [MyOutH], @Attr
;       INVOKE  WriteConsole, [MyOutH],  OFFSET MsgText1, [LenText1], ADDR NumWrt, 0
        INVOKE  WriteConsole, [MyOutH],  @Msg, @Len, ADDR NumWrt, 0
        ENDM
ELSE

; DOS version to write to mode 3 screen.

@PutText MACRO @Col, @Row, @Attr, @Msg, @Len    ; Msg's and Len's could be
        MOV     [Col],@Col                      ; combined due to consistant
        MOV     [Row],@Row                      ; definitions.
        MOV     AH,@Attr    ; Attribute
        MOV     SI, OFFSET @Msg
        MOV     CX,@Len
        CALL PutText    ; And print the text.
        ENDM
ENDIF

END

TIA,

Steve N.

jj2007

Try this:

@PutText MACRO @Col, @Row, @Attr, @Msg, @Len    ; Msg's and Len's could be
  mov eax, @Row
  shl eax, 16
  mov ax, @Col
  INVOKE SetConsoleCursorPosition, MyOutH, EAX
  INVOKE SetConsoleTextAttribute, MyOutH, @Attr
  INVOKE WriteConsole, MyOutH, reparg(@Msg), @Len, ADDR NumWrt, 0
ENDM
...
.DATA?
MyOutH dd ?
NumWrt dd ?
.CODE
start:
... set MyOutH etc ...
@PutText 3, 6, FOREGROUND_BLUE or BACKGROUND_RED, "Hello", 5

NoCforMe

One thing I don't understand about your macro:
  mov eax, @Row
  shl eax, 16
  mov ax, @Col
How can you move two of the macro parameters to different-size registers (32-bit / 16-bit)? Aren't all the parameters 32-bit?
Assembly language programming should be fun. That's why I do it.

sinsi

Quote from: NoCforMe on March 24, 2024, 04:04:11 PMOne thing I don't understand about your macro:
  mov eax, @Row
  shl eax, 16
  mov ax, @Col
How can you move two of the macro parameters to different-size registers (32-bit / 16-bit)? Aren't all the parameters 32-bit?

Macro parameter size for ml.exe would be 32-bits by default/design, but it's what you do with them that counts.
@Row fits into (in this case) a 32-bit register, just like @Col fits into a 16-bit register.
This fills a COORD structure, which is 4 bytes in length which can be pushed. It's unusual for Windows to have a structure as an arg, it would usually be a pointer to the structure.

jj sometimes forgets that simple is also ok.
(@Row shl 16) + @Col ;give EAX a rest

daydreamer

Quote from: NoCforMe on March 24, 2024, 04:04:11 PMOne thing I don't understand about your macro:
  mov eax, @Row
  shl eax, 16
  mov ax, @Col
How can you move two of the macro parameters to different-size registers (32-bit / 16-bit)? Aren't all the parameters 32-bit?
Best to convert to use all to 32 bit variables,in 32 bit you get an extra 66h prefix byte before all 16 bit register size and prevent bug when 65535 isnt enough

my none asm creations
https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
I am an Invoker
"An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
Like SIMD coding

NoCforMe

Quote from: sinsi on March 24, 2024, 04:51:30 PM
Quote from: NoCforMe on March 24, 2024, 04:04:11 PMOne thing I don't understand about your macro:
  mov eax, @Row
  shl eax, 16
  mov ax, @Col
How can you move two of the macro parameters to different-size registers (32-bit / 16-bit)? Aren't all the parameters 32-bit?

Macro parameter size for ml.exe would be 32-bits by default/design, but it's what you do with them that counts.
@Row fits into (in this case) a 32-bit register, just like @Col fits into a 16-bit register.
This fills a COORD structure, which is 4 bytes in length which can be pushed. It's unusual for Windows to have a structure as an arg, it would usually be a pointer to the structure.

Still confused here: so those macro parameters (@Col, @Row) have no defined size? they're just placeholders for whatever the macro is invoked with? That wasn't clear at all here (remember that I'm not a macro user, so what's obvious to JJ might be clear as mud to others here).

So if I invoke the macro like so:
@PutText CX, EDX, [attr], [msg], [len]
then it'll work because the macro will assemble
  mov eax, EDX
  shl eax, 16
  mov ax, CX
Izzat right?

Seems weird to have row & col. be 2 different size vars.
Assembly language programming should be fun. That's why I do it.

sinsi

QuoteSeems weird to have row & col. be 2 different size vars.

You missed the bit about a COORD structure. This has two members, X and Y, both 16-bit words.
When you lay it out in memory, the low word is X and the high word is Y.
It just so happens that EAX is the size of a COORD, and since you can't load the upper 16-bits of a 32-bit register there's the 'trick' of shifting it.

Assuming @Row is 0..79, you could mov it into AL, AH, EAX or RAX. It all depends on what you are going to do with it.

NoCforMe

Yeah, I get that. But what seems weird is that in the macro, @Row is a DWORD and @Col is a WORD.
Assembly language programming should be fun. That's why I do it.

sinsi

No, they are both integers, no size is specified. 

sinsi

Put it this way, if a COORD was 2 bytes you would use this (not realistically, just to explain)
    mov al,@Row
    shl ax,8
    mov al,@Col

AFAIK you can't specify a size or type in a macro definition.

jj2007

Quote from: sinsi on March 24, 2024, 04:51:30 PMjj sometimes forgets that simple is also ok.
Code Select Expand
(@Row shl 16) + @Col ;give EAX a rest

As Einstein said, "everything should be made as simple as possible, but not simpler" :azn:

  m2m ebx, 3
  .Repeat
    lea esi, [4+4*ebx]
    @PutText esi, ebx, FOREGROUND_RED or FOREGROUND_GREEN or FOREGROUND_BLUE, str$(ebx)
    inc ebx
  .Until ebx>20



                3
                    4
                        5
                            6
                                7
                                    8
                                        9
                                            10
                                                11
                                                    12
                                                        13
                                                            14
                                                                15
                                                                    16
                                                                        17
                                                                            18
                                                                                19
                                                                                    20

Source attached, purest Masm32 SDK code ;-)

NoCforMe

Quote from: sinsi on March 24, 2024, 08:01:32 PMNo, they are both integers, no size is specified.

Well, yes and no. The way the macro is written, @Row must be a DWORD and @Col must be a WORD, otherwise you'll get assembler errors. Therefore the code in the macro dictates the size of those vars, even though as you say there is no type declaration for them.
Assembly language programming should be fun. That's why I do it.

FORTRANS

Hi,

   Thanks to all.  The discussion between NoCforMe and sinsi
was interesting.  It probably helps.  But it will require some
usage to make sure.

   @Jochen:  Can reparg be used as below?  And does "OFFSET"
add anything?  And are all the macro invocations below valid?
What are your style preferences (if any)?

.DATA

LenText1 DD     36
MsgText1 DB     ' Fixed Point to Decimal Calculator. '
LenText2 DD     79
MsgText2 DB     ' X/x = Exit, 1 = Set, 0 = Reset, Space = Toggle, Left = comma, Right = period. '

Msg_Row DB      ' RowWork  '


.CODE
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

;  And print it, Col Row Attr Text TextLength
        @PutText  19, 0, 1BH, OFFSET MsgText1, OFFSET LenText1 ; Title
        @PutText  2, 1, 10, MsgText2, LenText2  ; Instructions
        @PutText  19, 3, 10, reparg(" Say what?"), 10
;  And print title, Col Row Attr Text TextLength
        @PutText  27, 0, 39H, Msg_Row, 10

Regards,

Steve N.

NoCforMe

Sorry, nitpick here:
LenText1 DD    36
MsgText1 DB    ' Fixed Point to Decimal Calculator. '
Ugh. Very ugly. Pain in the butt. Count characters? Yuck.

Couple better ways to do this:
1. Use standard NULL-terminated strings and use strlen() to get their length at runtime.
2. If you want prefer to get the string length at assemble time, the assembler is your friend:
MsgText1 DB ' Fixed Point to Decimal Calculator. '
$MsgTextLength EQU $ - MsgText1
and use the constant $MsgTextLength when you need it.
Assembly language programming should be fun. That's why I do it.

jj2007

Quote from: NoCforMe on March 25, 2024, 06:08:18 AMThe way the macro is written, @Row must be a DWORD and @Col must be a WORD, otherwise you'll get assembler errors

If you had downloaded the source of reply #10 and had a look at it, you would know that this is not true.

Quote from: FORTRANS on March 25, 2024, 08:20:55 AMCan reparg be used as below?

Maybe. I've never used it as an argument, but it might work. Why don't you test it?