我正在学习汇编语言并尝试解决以下问题。我编写了代码,但它不起作用。
编写一个程序,使用循环计算由下式描述的Fibonacci数序列的前七个值:Fib(1)= 1,Fib(2)= 1,Fib(n)= Fib(n - 1)+ Fib(n-2)。
我需要用汇编语言编写的这个程序。使用程序模板中的注释作为使用汇编语言编写代码的说明。我希望用这种编程逻辑用汇编语言编写程序:
.data
;declare an array
.code
main proc
;move 0 into ebx to initialize
;move 1 into edx to store the first Fib value
;move edx into an array ; store the first Fib value
; prepare to loop
; loop counter for 6 more values
; move esi,4
; array index for 3rd Fib value
L1:
;move ebx into eax
;add edx and eax
;move edx into the array of esi
; eax = ebx
; eax = eax + edx
; store the Fib value
;move edx into ebx
; prepare for next iteration
;move eax into edx
;add 4 to esi
;Loop L1
invoke ExitProcess,0
我的代码:
ExitProcess PROTO
.data
numbers DWORD 10 DUP (?)
.code
main PROC
mov ebx,0
mov edx,1
mov numbers,edx
mov ecx,6
mov esi,4
L1:
mov eax,ebx
add eax,edx
mov esi,OFFSET numbers
mov [esi],edx
mov eax,ebx
add eax,edx
mov edx,ebx
mov eax,edx
add esi,4
Loop L1
call ExitProcess
main ENDP
END
我将代码编辑为以下内容:
ExitProcess PROTO
.data
numbers DWORD 10 DUP (?)
.code
main PROC
mov ebx,0
mov edx,1
mov numbers,edx
mov ecx,10
mov esi,4
mov esi,OFFSET numbers
L1:
mov eax,ebx
add eax,edx
mov [esi],edx
mov ebx,edx
mov edx,eax
add esi,4
Loop L1
call ExitProcess
main ENDP
END
当我逐步执行代码时,eax寄存器和edx寄存器将显示Fibonacci序列值:1,2,3,5,8,13等。但是,代码是否存储eax寄存器或edx寄存器数字数组中的值?如果不是我该怎么做。
这是一行有效的代码吗?它是否将edx值存储在数字数组中?
mov numbers,edx
如何将eax或edx值存储在数字数组中?
答案 0 :(得分:0)
代码中的一些问题:
mov esi,OFFSET numbers
mov [esi],edx
这将在每次写入之前初始化esi
,因此您将覆盖元素" numers [0]"一直以来。
mov eax,ebx
add eax,edx
mov edx,ebx
mov eax,edx
这没有多大意义......首先你计算eax = ebx+edx
...第二次(eax已经包含了前一行的那个值)。
然后你做eax = edx = ebx;
(即你将ebx复制到eax和edx中)
您可能想要反过来这样做,例如:mov ebx,edx mov edx,eax
。
"移动esi,4"从原始评论中没有意义,它会像add esi,4
那样有意义,你在numbers
中已经有了esi
地址(就像下一个代码那样)。
但看起来你并不了解地址是什么,所以在"存储Fib值"你一次又一次地加载地址。重点是只将esi
设置为数组的开头一次,然后在每次写入后更新指针以指向下一个空闲空间。
总体上得到一些调试器,并在每条指令后逐步开始观察寄存器和内存,将它与每条指令描述进行比较,直到它对你熟悉,它们做什么,它从代码看起来你没有线索那些指示实际上是做什么的。
现在尝试理解这一点:
mov esi,OFFSET numbers ; esi = target array address
mov ecx,7 ; produce seven numbers
xor ebx,ebx ; ebx = 0 F(-1)
mov edx,1 ; edx = 1 F(0)
jmp store_number
loop1:
add ebx,edx ; ebx: F(n) = edx: F(n-1) + ebx: F(n-2)
xchg ebx,edx ; ebx: F(n-1), edx: F(n)
store_number:
mov [esi],edx ; array_pointer[0] = F(n)
add esi,4 ; ++array_pointer
loop loop1
还要注意有多少指令正在进行纯纸配方工作(" F(n)= F(n-1)+ F(n-2)")和" 7号"有多少指令只是为了支持这件事。你可能不同意,但我会说cca。 50%是"支持cru",大部分是直接纸 - >代码重写。
在学习汇编时请记住这一点,确保首先清楚地了解您希望在公式级别实现的目标,然后尝试 ...仅在绝对必要时添加支持代码。不要只写一些随机指令,因为它看起来不错,或者你之前就这样写过。指令要么"做一些你想要的东西",或者把它剪掉。
编辑评论:
mov esi,OFFSET numbers
存储符号的地址"数字"进入esi
。如果您将numbers
声明为BYTE
或DWORD
,则地址指向分配的内存的第一个位置(第一个字节),这一点并不重要。
byte / dword / dup对于分配足够的总空间很重要,但不会影响地址本身("符号")。
mov [aaa],vvv
存储价值" vvv"在地址" aaa" (查看说明指南以查看可能的组合)。
因此mov [esi],edx
之后mov esi,OFFSET numbers
会将每个值存储在"数字[0]和#34;中。在调试器中查看esi
每次mov esi,OFFSET numbers
重置的方式。
请不要使用quirk syntax mov numbers,edx
,它将值存储到"数字"数组仅在MASM中(以及在模拟MASM怪癖模式时为TASM),在适当的英特尔语法中使用[]
信号解除对指针/地址的引用,因此在读取源代码时很容易判断指令是否有效仅具有寄存器/立即值,或者它是否访问内存。 (lea reg,[address]
是例外,它不访问内存,只计算地址)。在NASM中,mov numbers,edx
根本不会编译,mov edx,numbers
不会从数组加载第一个值,但是地址本身(在MASM / TASM中你必须在符号之前写OFFSET)。
所以
"代码是否将eax寄存器值存储在数字数组中?"
不,它只会覆盖第一个numbers[0]
值。