我在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),但我只有构建错误或输出不正确。你能告诉我正确的解决方案吗?
答案 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]