Assembly NASM汇编积分计算器
我必须建立一个NASM汇编程序,它将使用1000个切片的梯形规则对a到b进行定积分。对于任何不知道这是什么的人来说,它是b-a/2N*(f(x)+2(f(x1)+2(f(x2))+…+2(f(xN))+2(f(xN+1)) f的函数是sin(x),所以每次迭代都必须有sin(x+interval(interval在我的代码中用'n'表示))取并乘以2。我必须在子例程中完全不使用特殊运算符或函数进行此操作。主函数只接受初始x值和结束x值的值,并将它们传递给子例程。子例程返回一个y值,它是函数的和。我让它至少在取将x的正弦值乘以2,并将其存储到下一个x的正弦值中,但最终经过大约30次循环后,它会给我一个 下面是我到目前为止的子程序代码:Assembly NASM汇编积分计算器,assembly,nasm,integral,Assembly,Nasm,Integral,我必须建立一个NASM汇编程序,它将使用1000个切片的梯形规则对a到b进行定积分。对于任何不知道这是什么的人来说,它是b-a/2N*(f(x)+2(f(x1)+2(f(x2))+…+2(f(xN))+2(f(xN+1)) f的函数是sin(x),所以每次迭代都必须有sin(x+interval(interval在我的代码中用'n'表示))取并乘以2。我必须在子例程中完全不使用特殊运算符或函数进行此操作。主函数只接受初始x值和结束x值的值,并将它们传递给子例程。子例程返回一个y值,它是函数的和。
.data
two REAL8 2.0
half REAL8 0.5
x REAL8 ?
n REAL8 ?
i dword 1000
thos REAL8 1000.0
sum REAL8 0.0
sum2 REAL8 ?
sum3 REAL8 ?
.code
integral1 PROC
PARAMS = 2*TYPE DWORD
NPARAMS = 3
x2$ = PARAMS+0*TYPE DWORD
x1$ = PARAMS+1*TYPE DWORD
y$ = PARAMS+2*TYPE DWORD
pushfd
;BELOW: Calculate interval
mov ebx,x2$[esp]
fld REAL8 PTR [ebx]
mov ebx,x1$[esp]
fld REAL8 PTR [ebx]
fsub
fdiv thos
fstp n
;BELOW: calculate 1/2 of interval per trapezoidal rule
fld n
fld half
fdiv
fstp half
;BELOW: load 1000 into counter register and store x variable
mov ecx,i
fld REAL8 PTR [x1]
fstp x
;BELOW: f(x) calculation
fld REAL8 PTR [x]
fsin
fstp sum2
for_loop:
fld REAL8 PTR [x]
;load x onto stack
fld REAL8 PTR [n]
;load interval onto stack
fadd
;add x and interval
fst x
;store value in x for later use
fsin
;take sine of x
fmul two
;multiply by 2 to get 2(f(x))
fst sum3
;store value in arbitrary variable
fld sum
;load current total of functions
fadd
;add sum3 to sum
fst sum
;store sum and loop
cmp ecx,0
je end_for
dec ecx
jmp for_loop
end_for:
fld REAL8 PTR [sum]
fmul half
;multiply sum by 1/2
fadd sum2
;add sine(x) to total before pushing back to main
mov ebx,y$[esp]
fstp REAL8 PTR [ebx]
popfd
ret NPARAMS*TYPE DWORD
integral1 ENDP
END main
如果有人能帮我理解为什么要这样做,或者我的错误在哪里,或者如何纠正,我将永远感激。我已经做了6个多小时了,我已经没有主意了。你确定这是NASM。代码似乎是MASM?x87基本上已经过时了,除了80位精度,64位双精度还不够。如果您使用的是64位临时变量,那么您就失去了x87相对于SSE/SSE2的唯一优势。(还要注意,
fsin
指令比好的数学库sin
实现更慢、更不准确。不过,我认为准确度是。请参阅关于该线程的讨论,了解您可以预期的ULP错误数量)I,即使是不需要缩小范围的小参数也会发生这种情况。相比之下,FP mul/add/sub结果始终精确到0.5 ulp(即正确四舍五入).我认为glibc的libm实现的目标是在数学函数中达到这样的精度水平。这可能对你来说很重要,也可能不重要。我假设你这样做是作为一个asm学习练习,因为C会更容易。在未问问题的领域,这是带有Irvine库的NASM汇编程序。我没有问关于精度的问题,这不是iss我必须计算纸上的绝对和相对误差。NASM不使用您正在使用的语法。您确定没有将其与MASM(Microsoft Assembler)混淆。NASM不使用REAL8(或REAL4),它不理解.code
和.data
指令,并且不支持内存操作数上的ptr
修饰符。但是,所有这些都可以与MASM一起使用