Search code examples
assemblymasmmasm32

How can I print array on MASM32?


I have program on MASM32 which solve a simple piecewise-defined function. In pseudo-code it's:

if (a > b) x = 2 + b/a
else if (a == b) x = 25
else x = (a - 5)/b

I input a, b, h and n. In loop program makes n steps (a = a + h, x = ...) and writes result of piecewise to array. Now I must write function for print array. This is the code:

include \masm32\include\masm32rt.inc

.const

    two     dq  2.
    five    dq  5.
    twfive  dq  25.

    enterA  db  "a: ", 0
    enterB  db  "b: ", 0
    enterH  db  "h: ", 0
    enterN  db  "n: ", 0

    InputFormat     db  "%lf", 0
    InputNFormat    db  "%d", 0

    OutputFormat    db  "%f", 10, 0
    OutputFormatD   db  "%d", 10, 0

.data

.data?

    a   dq  ?
    b   dq  ?
    h   dq  ?
    n   dd  ?
    tmp dq  ?
    l   dd  0

    arr dq 50 dup(0) 

.code

    main proc
        FINIT           ; init of coprocessor

        invoke crt_printf, addr enterA
        invoke crt_scanf, addr InputFormat, addr a

        invoke crt_printf, addr enterB
        invoke crt_scanf, addr InputFormat, addr b

        invoke crt_printf, addr enterH
        invoke crt_scanf, addr InputFormat, addr h

        invoke crt_printf, addr enterN
        invoke crt_scanf, addr InputNFormat, addr n

        MOV ECX, n      ; ECX = n = number of loop repetition
        MOV EDI, 0      ; EDI = 0

        FLD a           ; ST(0) = a

        cycle:

            FCOM b      ; compare a and b, result in SWR
                        ; C2 = 1 => incomparable
                        ; C0 = 1 => a < b
                        ; C3 = 1 => a = b
                        ; else   => a > b 
            FSTSW AX    ; SWR to AX
            SAHF        ; ZF = C3, PF = C2, CF = C0

            JP incomparable
            JC less
            JZ equal
            ;else a > b:

            FLD b       ; ST(0) = b, ST(1) = a
            FDIVR       ; ST(0) = b / a 
            FADD two    ; ST(0) = 2 + b / a

            JMP endc

        incomparable: 
            ;

        less:
            FSUB five   ; ST(0) = a - 5
            FDIV b      ; ST(0) = (a - 5) / b

            JMP endc

        equal:
            FSTP tmp    ; ST is empty
            FLD twfive  ; ST(0) = 25

            JMP endc

        endc:
            FSTP arr[EDI]
            ADD EDI, 8
            ADD l, 1

            FLD a       ; ST(0) = a
            FADD h      ; ST(0) = a + h
            FST a       ; a = ST(0)
            LOOP cycle

            ; all code above works perfect

            ; sodom and gomorrah will be here

            inkey
            invoke ExitProcess, NULL

    main endp

    end main 

So, first I was trying write a function but I had problems with passing parameters to it. I've decided to try put offset to register, push to stack, then pop it and print (at least) a first element of array. But I get many mistakes.

MOV EDI, offset arr  ; move offset of array to EDI
XOR ECX, ECX         ; clear ECX (but not increment yet)
PUSH QWORD [EDI + ECX * 8]  ; found this solution (but with dword, not qword) 
POP QWORD [tmp]             ; on stackoverflow, but it is not working :c

invoke crt_printf, addr OutputFormat, tmp

Then I tried to replace push/pop operations to mov :

MOV [tmp], [EDI + ECX * 4]

Nothing. And I can't use only registers because I use DQ (afaik registers are 32-bit, DQ — 64-bit).

I tried a lot of ways (for example FLD/FSTP), but I have only build-errors or incorrect output. Could you tell me the correct solution?


Solution

  • PUSH/POP r/m64 isn't valid in 32-bit mode (even if it had been, the correct MASM syntax would've been QWORD PTR [... rather than just QWORD [...).

    But there are other ways to move your data:

    • You could use two PUSH DWORD PTR instructions that each push half of the data, and then two POP DWORD PTR instructions to pop the data into place.

    • You could use the MOVQ instruction to transfer the data through an MMX register (you'll need to add the .mmx directive to the beginning of your assembly file for this to assemble):

      movq mm0,[EDI + ECX * 8]
      movq [tmp],mm0
      emms

    • You could move the data using the FPU:

      fld QWORD PTR [EDI + ECX * 8]
      fstp QWORD PTR [tmp]