我想我在汇编程序中以某种方式错误地使用了循环。任务文字:
计算函数 Yn = 37/(2x^2+7.3) 的 4 个值(x 随着步骤 2 从 1 变化)。
这是我的程序代码:
;Розрахувати 4 значень функції Y = 37/(2x^2+7.3) (x змінюється с шагом 2.0).
.386
.model flat, stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
include \masm32\include\fpu.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\fpu.lib
.data
CrLf equ 0A0Dh
_y1 dt 0.0 ;объявляем у1
_y2 dt 0.0 ;объявляем у2
_y3 dt 0.0 ;объявляем у3
_y4 dt 0.0 ;объявляем у4
_temp1 DWORD ? ;создаём темп
_two DWORD 2.0 ;создаём константу с значеием 2.0
_x DWORD 1.0 ;создаём константу с значеием 1.0
_op1 DWORD 37.0 ;создаём константу с значеием 37.0
_op2 DWORD 7.3 ;создаём константу с значеием 7.3
_zero DWORD 0.0 ;создаём константу с значеием 0.0
_step DWORD 2.0 ;создаём константу с значеием 2.0
info db "Batyuk Bogdan Stundent of KNEU",10,10,
"Y = 37/(2x^2+7.3), x change with step 2.0",10,10,
"y1 = "
_res1 db 11 DUP(0),10,10
db "y2 = "
_res2 db 11 DUP(0),10,10
db "y3 = "
_res3 db 11 DUP(0),10,10
db "y4 = "
_res4 db 12 DUP(0),10,10
ttl db "Calculating",0
.code
_start:
finit
mov ecx, 4
m1: fld _x ;вводим в стек х
fmul _x ;x*x=x^2
fmul _two ;x^2*2
fadd _op2 ;x^2*2+7.3
fdivr _op1 ;37/x^2*2+7.3
fld _x ;вносим в стек х
fadd _step ;x+step (1+2)
fstp _x ;вивидом значеием из стека
loop m1 ;зацикливаем m1
fstp _y4 ;
fstp _y3 ;
fstp _y2 ;
fstp _y1 ;
invoke FpuFLtoA,offset _y1,10,offset _res1,SRC1_REAL or SRC2_DIMM
mov word ptr _res1 + 11, CrLf
invoke FpuFLtoA,offset _y2,10,offset _res2,SRC1_REAL or SRC2_DIMM
mov word ptr _res2 + 11, CrLf
invoke FpuFLtoA,offset _y3,10,offset _res3,SRC1_REAL or SRC2_DIMM
mov word ptr _res3 + 11, CrLf
invoke FpuFLtoA,offset _y4,10,offset _res4,SRC1_REAL or SRC2_DIMM
invoke MessageBox, 0, offset info, offset ttl, MB_ICONINFORMATION
invoke ExitProcess, 0
end _start
FpuFLtoA
存储以 null 结尾的字符串,因此在第一次调用后 _res1
在末尾包含字节 0
。 MessageBox
显示以 null 结尾的字符串,因此它会忽略字节 0
之后的所有内容。
解决方案之一是在运行时通过复制所需的组件来组成“answer”字符串。
我修改了您程序中与结果转换相关的部分,并保留了原样的计算部分。
...
; First modified part concerns data organization in `.data` section and
; introduces `.data?` section for results:
info db "Batyuk Bogdan Stundent of KNEU",10,10,
"Y = 37/(2x^2+7.3), x change with step 2.0",10,10
info_len = $ - info
str_eq db "y0 = " ; index "0" is updated in code
str_eq_len = $ - str_eq
ttl db "Calculating",0
.data?
_res db 16 DUP(?)
_res_len = $ - _res
; reserve space for answer: info + 4 results
answer db (info_len + (str_eq_len + _res_len + 2) * 4) dup(?)
; End of first modified part
.code
_start:
finit
mov ecx, 4
m1: fld _x ;вводим в стек х
fmul _x ;x*x=x^2
fmul _two ;x^2*2
fadd _op2 ;x^2*2+7.3
fdivr _op1 ;37/x^2*2+7.3
fld _x ;вносим в стек х
fadd _step ;x+step (1+2)
fstp _x ;вивидом значеием из стека
loop m1 ;зацикливаем m1
fstp _y4 ;
fstp _y3 ;
fstp _y2 ;
fstp _y1 ;
; Second modified part: compose answer string
mov ebx, offset _y1 ; address of first stored answer
mov edi, offset answer ; store answer string here
cld ; direction for string opearations: incrementing
; copy info string to answer
mov esi, offset info
mov ecx, info_len
rep movsb
mov ecx, 4 ; will print 4 numbers
m2: push ecx
; copy "yN = " string
mov esi, offset str_eq
inc byte ptr [esi + 1] ; update y index
mov ecx, str_eq_len
rep movsb
; convert result to string
invoke FpuFLtoA, ebx, 10, edi, SRC1_REAL or SRC2_DIMM
; scan for end of line in converted result
mov ecx, _res_len
xor al,al
repnz scasb
pop ecx
loop cont ; continue if not last element
; show message box and exit if all elements processed
invoke MessageBox, 0, offset answer, offset ttl, MB_ICONINFORMATION
invoke ExitProcess, 0
cont:
dec edi ; go back for 1 char
mov ax, CrLf
stosw ; store CR/LF
add ebx, 10 ; take next stored result. extended float: 10 bytes
jmp m2
end _start