汇编语言代码问题

时间:2016-10-11 01:54:12

标签: assembly

我正在学习汇编语言并尝试解决以下问题。我编写了代码,但它不起作用。

  

编写一个程序,使用循环计算由下式描述的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值存储在数字数组中?

1 个答案:

答案 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声明为BYTEDWORD,则地址指向分配的内存的第一个位置(第一个字节),这一点并不重要。

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]值。