2014-12-19 92 views
1

我有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 = ...)并将结果分段写入数组。现在我必须为打印阵列写功能。这是代码:

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 

然后我试图取代推/弹出操作MOV:

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

没有。我不能只使用寄存器,因为我使用DQ(afaik寄存器是32位,DQ-64位)。我试过很多方法(例如FLD/FSTP),但我只有构建错误或输出不正确。你能告诉我正确的解决方案吗?

回答

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]

+0

非常感谢解释!我选择最后的方式。 – 2014-12-19 08:43:48