2014-12-19 101 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