[英]Assembly Language Code issue
我正在自己的时间学习汇编语言并试图解决以下问题。 我写了代码,但它不起作用。
编写一个程序,使用循环计算由以下公式描述的斐波那契数列的前七个值: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 寄存器将显示斐波那契数列值:1、2、3、5、8、13 等。但是,代码是否将 eax 寄存器或 edx 寄存器值存储在数字数组? 如果不是我该怎么做。
这是有效的代码行吗? 它是否将 edx 值存储在 numbers 数组中?
mov numbers,edx
如何在 numbers 数组中存储 eax 或 edx 值?
您的代码中的一些问题:
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
。
原始评论中的“move esi,4”没有意义, add esi,4
会有意义,您是否已经在esi
有numbers
地址(就像下一个代码那样)。
但看起来你不明白地址是什么,所以在“存储 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% 是“支持 cruft”,大部分是直接论文 -> 代码重写。
学习大会时,请记住这一点,确保你有你想要达到的公式层次什么第一思路很清晰,然后尝试这样做...添加支持的代码只有在绝对必要。 不要只写一些随机的指令,因为它看起来是个好主意,或者你以前是这样写的。 指令要么“做一些你想做的事情”,要么把它删掉。
编辑评论:
mov esi,OFFSET numbers
将符号“数字”的地址存储到esi
。 如果您将numbers
声明为BYTE
或DWORD
并不重要,地址指向分配的内存的第一个位置(第一个字节)。
byte/dword/dup 对于分配足够的总空间很重要,但不影响地址本身(“符号”)。
mov [aaa],vvv
将值“vvv”存储到地址“aaa”的内存中(查看指令指南以查看可能的组合)。
所以mov [esi],edx
在mov esi,OFFSET numbers
之后mov esi,OFFSET numbers
会将每个值存储在“numbers[0]”处。 在调试器中查看, esi
是如何通过mov esi,OFFSET numbers
每次重置的。
并且请不要使用怪癖语法mov numbers,edx
,它仅在 MASM(和模拟 MASM 怪癖模式时的 TASM)中将值存储到“数字”数组中,在正确的英特尔语法中,使用[]
表示取消引用指针/地址,因此在读取源代码时很容易判断指令是仅使用寄存器/立即数操作,还是访问内存。 ( lea reg,[address]
是例外,不访问内存,只计算地址)。 在 NASM 中, mov numbers,edx
根本不会编译,并且mov edx,numbers
不会从数组加载第一个值,而是加载地址本身(在 MASM/TASM 中,您必须在符号之前写入 OFFSET)。
所以
“代码是否将 eax 寄存器值存储在数字数组中?”
不,它只覆盖第一个numbers[0]
值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.