如何在MASM32上打印数组?

时间:2014-12-19 08:14:30

标签: assembly masm masm32

我在MASM32上有程序,它解决了一个简单的分段定义函数。在伪代码中它是:

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

我输入a,b,h和n。在循环程序中进行n步(a = a + h,x = ...)并将分段结果写入数组。现在我必须为print数组编写函数。这是代码:

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 

所以,首先我尝试编写一个函数,但是我遇到了将参数传递给它的问题。我决定尝试将偏移量注册,推送到堆栈,然后弹出并打印(至少)数组的第一个元素。但是我犯了很多错误。

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

然后我尝试将push / pop操作替换为mov:

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

无。我不能只使用寄存器,因为我使用DQ(afaik寄存器是32位,DQ - 64位)。

我尝试了很多方法(例如FLD / FSTP),但我只有构建错误或输出不正确。你能告诉我正确的解决方案吗?

1 个答案:

答案 0 :(得分:0)

PUSH/POP r/m64在32位模式下无效(即使它已经存在,正确的MASM语法将是QWORD PTR [...而不仅仅是QWORD [...)。

但是还有其他方法可以移动您的数据:

  • 您可以使用两条PUSH DWORD PTR指令,每条指令推送一半数据,然后使用两条POP DWORD PTR指令将数据弹出到位。

  • 您可以使用MOVQ指令通过MMX寄存器传输数据(您需要将.mmx指令添加到汇编文件的开头,以便汇编) :

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

  • 您可以使用FPU移动数据:

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