News:

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

Main Menu

Included files from MASM64 SDK being weird; MASM beginner

Started by Honzik2005, January 04, 2025, 09:45:14 PM

Previous topic - Next topic

Honzik2005

Hello, this is my first real post here. For my first real project in assembly, I want to make some simple graphics using the Windows API and see where I can go from there. When I run this simple dialog box program, which includes win64.inc, everything runs fine:

option casemap:none

include masm64\include64\win64.inc
includelib masm64\lib64\kernel32.lib
includelib masm64\lib64\user32.lib

externdef MessageBoxA : near
externdef ExitProcess : near

.data
  text    db 'Hello world!', 0
  caption db 'Hello x86-64', 0
.code

main proc
  sub rsp, 28h
  xor r9d, r9d
  lea r8, [caption]
  lea rdx, [text]
  xor rcx, rcx
  call MessageBoxA
  xor ecx, ecx
  call ExitProcess
main endp

end

However, when I ran this code, which does pretty much nothing other than do some includes:

option casemap:none

include masm64\include64\win64.inc
includelib masm64\include64\gdi32.lib
includelib masm64\include64\user32.lib
include masm64\include64\kernel32.inc
includelib masm64\lib64\kernel32.lib

option casemap:none

.data

.code
main proc
    invoke ExitProcess,0
main endp
end

I got these two errors:

\masm64\include64\win64.inc(328) : error A2008:syntax error : in structure
graphics64.asm(17) : error A2008:syntax error : invoke

I tried to focus on the seemingly easier error to fix first, which was the fact that the term "invoke" wasn't being recognized. I looked at my Fibonacci sequence program, which uses "invoke," and I realized that the only difference was that my Fibonacci sequence program included masm64rt.inc. Bizarrely, when I did the same in my do-nothing program and tried to assemble it, I got these errors... not from masm64rt.inc, but yet again from win64.inc:

\masm64\include64\win64.inc(328) : error A2008:syntax error : in structure
\masm64\include64\win64.inc(195) : error A2163:non-benign structure redefinition: incorrect initializers : LARGE_INTEGER
\masm64\include64\win64.inc(196) : error A2163:non-benign structure redefinition: incorrect initializers : LARGE_INTEGER
\masm64\include64\win64.inc(199) : error A2163:non-benign structure redefinition: incorrect initializers : LARGE_INTEGER
\masm64\include64\win64.inc(293) : error A2163:non-benign structure redefinition: incorrect initializers : EXCEPTION_DEBUG_INFO
\masm64\include64\win64.inc(305) : error A2163:non-benign structure redefinition: incorrect initializers : DEBUG_EVENT
\masm64\include64\win64.inc(306) : error A2163:non-benign structure redefinition: incorrect initializers : DEBUG_EVENT
\masm64\include64\win64.inc(307) : error A2163:non-benign structure redefinition: incorrect initializers : DEBUG_EVENT
\masm64\include64\win64.inc(308) : error A2163:non-benign structure redefinition: incorrect initializers : DEBUG_EVENT
\masm64\include64\win64.inc(309) : error A2163:non-benign structure redefinition: incorrect initializers : DEBUG_EVENT
\masm64\include64\win64.inc(310) : error A2163:non-benign structure redefinition: incorrect initializers : DEBUG_EVENT
\masm64\include64\win64.inc(311) : error A2163:non-benign structure redefinition: incorrect initializers : DEBUG_EVENT
\masm64\include64\win64.inc(312) : error A2163:non-benign structure redefinition: incorrect initializers : DEBUG_EVENT
\masm64\include64\win64.inc(313) : error A2163:non-benign structure redefinition: incorrect initializers : DEBUG_EVENT
\masm64\include64\win64.inc(315) : error A2163:non-benign structure redefinition: incorrect initializers : DEBUG_EVENT
\masm64\include64\win64.inc(328) : error A2008:syntax error : in structure
\masm64\include64\win64.inc(336) : error A2163:non-benign structure redefinition: incorrect initializers : TOKEN_PRIVILEGES
\masm64\include64\win64.inc(337) : error A2164:non-benign structure redefinition: too few initializers : TOKEN_PRIVILEGES
\masm64\include64\win64.inc(357) : error A2163:non-benign structure redefinition: incorrect initializers : SYSTEM_INFO
\masm64\include64\win64.inc(363) : error A2163:non-benign structure redefinition: incorrect initializers : SYSTEM_INFO
\masm64\include64\win64.inc(364) : error A2163:non-benign structure redefinition: incorrect initializers : SYSTEM_INFO
\masm64\include64\win64.inc(365) : error A2163:non-benign structure redefinition: incorrect initializers : SYSTEM_INFO
\masm64\include64\win64.inc(366) : error A2163:non-benign structure redefinition: incorrect initializers : SYSTEM_INFO
\masm64\include64\win64.inc(367) : error A2163:non-benign structure redefinition: incorrect initializers : SYSTEM_INFO
\masm64\include64\win64.inc(368) : error A2163:non-benign structure redefinition: incorrect initializers : SYSTEM_INFO
\masm64\include64\win64.inc(369) : error A2163:non-benign structure redefinition: incorrect initializers : SYSTEM_INFO
\masm64\include64\win64.inc(370) : error A2163:non-benign structure redefinition: incorrect initializers : SYSTEM_INFO
\masm64\include64\win64.inc(371) : error A2163:non-benign structure redefinition: incorrect initializers : SYSTEM_INFO
\masm64\include64\win64.inc(372) : error A2163:non-benign structure redefinition: incorrect initializers : SYSTEM_INFO
\masm64\include64\win64.inc(373) : error A2163:non-benign structure redefinition: incorrect initializers : SYSTEM_INFO
\masm64\include64\win64.inc(480) : error A2163:non-benign structure redefinition: incorrect initializers : TEXTRANGE
\masm64\include64\win64.inc(523) : error A2163:non-benign structure redefinition: incorrect initializers : IPAddr
\masm64\include64\win64.inc(529) : error A2163:non-benign structure redefinition: incorrect initializers : IPAddr
\masm64\include64\win64.inc(530) : error A2163:non-benign structure redefinition: incorrect initializers : IPAddr
\masm64\include64\win64.inc(531) : fatal error A1010:unmatched block nesting

I'm a bit out of my depth here. I can't imagine why an .inc file would work just fine with a simple dialog box program and yet throw an error on a program that does nothing, let alone why including one .inc file in a program would cause another one to freak out.

I'm putting this at the bottom because it's not as relevant, but this is the aforementioned Fibonacci sequence program that I wrote. Unlike my program that does nothing, it works. It's heavily commented because it took me several hours to get working and I learned a lot along the way:

include masm64\include64\masm64rt.inc
include masm64\include64\kernel32.inc
includelib masm64\lib64\kernel32.lib
option casemap:none

.data
    var1 dd 01h
    var2 dd 00h
    var3 dd 00h
    lim dd 0FFFFh
    buffer db 11 dup(0) ; Buffer to store converted number (10 digits + null terminator)
    newline db 0Dh, 0Ah, 0 ; Newline sequence (CR + LF + null terminator)
    debugline db ' ', 'L', 'I', 'N', 'E', 0
    counter dd 00h
.code
main proc
    mov eax,var1
    add eax,var2
    mov var3,eax

    mov eax,var2
    mov var1,eax
    mov eax,var3    ; Important as well for initializing EAX for convert_loop
    mov var2,eax

    jmp convert_loop
main endp

convert_loop:  ; PROCs set up a new stackframe, while simple labels don't -
                ; in the disassembled view in x64dbg, the beginning of every
                ; PROC has the two lines "enter 80,0" and "sub rsp,60"
                ; This is why values pushed in convert_loop couldn't be
                ; popped in into_buffer


    ; This loop recursively divides var3 by 10 and gets the remainder, which
        ; is mathematically guaranteed to be lowest decimal digit of the number.
    ; This method extracts one decimal digit (represented in binary) from a
    ; number per loop in the order of lowest to highest, pushing each value
    ; to the stack
    ; Example: 11000 / 1010 = Quotient: 10 Remainder: 100
    ; Decimal: 24    / 10  = Quotient: 2  Remainder: 4
   

    inc counter        ; Increment counter by 1
    mov rcx,10        ; Divisor (10)
    xor rdx,rdx        ; Clear RDX (remainder register)
    div rcx            ; RAX / 10 -> Quotient in RAX, Remainder in RDX

    add rdx, '0'

                    ;This logic is redundant /
   
    ; add dl, '0'      ; DL is lowest 8 bits of RDX, ASCII '0' is 030h,
                  ; only the lowest 8 bits of RDX are used because
                          ; the remainder of a decimal number divided by 10
                          ; is guaranteed to be between 0-9, therefore only
                          ; the first 8 bits (0-255) are relevant
    ; movzx rdx, dl    ; Zero-extend DL (8 bits) to RDX (64 bits); only
                          ; a full double word can be pushed to stack

                  ;This logic is redundant /
   
    push rdx          ; Push RDX to stack
    test rax, rax      ; AND RDX with itself to see if RDX (remainder) is
                          ; 0, since if it is 0, the final digit has been
                      ; acquired
    jnz convert_loop  ; Jump if not zero instruction
    mov rbx,00h        ; Initialize rbx to 0 for into_buffer
    jmp into_buffer    ; Jump to into_buffer

into_buffer:

    ; This loop takes the ASCII values from the stack and puts them
        ; into the buffer

    dec counter            ; Decrement counter by 1
    lea rcx,buffer          ; RCX points to the beginning of buffer
    add rcx,rbx            ; Add the current intra-buffer offset to RCX
    mov rax, 00h            ; Clear RAX
    pop rax                ; Move the top of the stack into RAX
    mov byte ptr [rcx],al  ; AL is always the lowest 8 bits of RAX, "byte" must be
                                ; specified so that the assembler knows the size of the
                                ; memory being addressed when it isn't clear from
                                ; context alone. mov al,bl would be fine since both
                                ; AL and BL are 8-bit registers. The brackets around
                                ; "rcx" moves the contents of AL into the memory
                    ; location that RCX points to instead of RCX itself
    inc rbx                ; Increment buffer offset by 1
    mov eax,counter   
    test eax,eax            ; See if counter is 0
    jnz into_buffer        ; If counter has not yet reached 0, repeat loop
    inc rcx                ; Null terminator was being written before RCX
                ; was incremented, causing the least significant
                ; bit of each Fibonacci number to disappear,
                ; explaining why the first six lines were empty
                ; and why the sequence afterwards didn't exactly
                ; match up with the Fibonacci sequence
    mov byte ptr [rcx],0    ; Add null terminator the end of the buffer, though this
                                ; is probably redundant, since buffer is initialized as
                                ; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 or 11 dup(0)
    jmp finish

finish:
    invoke StdOut, addr buffer              ; "addr" returns the memory address
                        ; of buffer
    ;invoke StdOut, addr debugline          ; Just prints the word "line" on
                        ; every line
    invoke StdOut, addr newline

    mov eax,var3
    cmp eax,lim
    jl main
   
    invoke ExitProcess,0

end

Thanks in advance for any advice! I find it extremely ironic that I'm trying to debug a program that does nothing even though my programs that actually do things work fine.

sinsi

The only file you need to include is masm64rt.inc, this file includes the main inc files (kernel32 etc).
Be aware that the MASM64 SDK is a work in progress and work has stalled since hutch's passing.

zedd151

QuoteHowever, when I ran this code, which does pretty much nothing other than do some includes:

option casemap:none

include masm64\include64\win64.inc
includelib masm64\include64\gdi32.lib
includelib masm64\include64\user32.lib
include masm64\include64\kernel32.inc
includelib masm64\lib64\kernel32.lib

look at your .inc and .lib file paths...(compared to your first example here) notice anything different about them?...  :winking:

Also each .lib file after win64.inc should have a corresponding .inc include file declared above it (and after win64.inc) you are missing gdi32.inc and user32.inc there... as well as the paths issue.


Or simply use "include masm64\include64\masm64rt64.inc" in place of all of those .inc and .lib declarations as sinsi suggested.  :smiley:

I looked at your fibonacci example, very nice.
Here is a program of my own, that generates fibonacci sequence up to any desired (reasonable) length.  It is 32 bit code but you might know how to convert it to 64 bit. I haven't had the time to do myself.
It uses an ascii string to store the "integers" and do the manipulations from that, rather than simple registers or variables - both of those of course have limits.
That program has a function 'ascii_adder' which as the name implies adds ascii strings to enable working with huge integers within the program.  :azn:

I also attached my 64 bit implementation of the Sieve of Eratosthenes for generating a sequence of prime numbers, for your amusement.
¯\_(ツ)_/¯