繁体   English   中英

汇编语言代码问题

[英]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会有意义,您是否已经在esinumbers地址(就像下一个代码那样)。

但看起来你不明白地址是什么,所以在“存储 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声明为BYTEDWORD并不重要,地址指向分配的内存的第一个位置(第一个字节)。

byte/dword/dup 对于分配足够的总空间很重要,但不影响地址本身(“符号”)。

mov [aaa],vvv将值“vvv”存储到地址“aaa”的内存中(查看指令指南以查看可能的组合)。

所以mov [esi],edxmov 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM