将数组中的数组转移到数组中以获得奇怪的输出。为什么?

时间:2019-04-30 19:21:50

标签: linux assembly x86 nasm

我试图理解如何为一个类操纵数组,但即使代码与我遇到此问题的支持材料中的代码完全相同

此网站中的代码使我对此有所启发 https://www.tutorialspoint.com/assembly_programming/assembly_arrays.htm 与我在代码中所做的运动部分也完全相同。 不知道是否与问题有关,即时通讯使用在线帮助:https://www.jdoodle.com/compile-assembler-nasm-online 运行代码。

section .text

global _start

_start:

    mov     eax,5
    mov     ebx,[x]
    mov     ecx,[y]
transfere:
    mov     ecx,ebx
    add     ebx,1
    add     ecx,1
    dec     eax
    jnz     transfere

    mov     [y],ecx


    mov     eax,4
    mov     ebx,1
    mov     ecx,y
    mov     edx,10
    int     0x80

    mov     eax, 1
    int     0x80

section .data

    x times 5 dw '5'
    y times 5 dw 0

我希望得到5.5.5.5.5。作为输出,但我得到9.5 .......

1 个答案:

答案 0 :(得分:1)

第一个问题是说明

    mov ebx, [x]
    mov ecx, [y]

只需将数组xy的前32位分别加载到ebxecx中。我假设您要执行的操作是将thes数组的地址加载到这两个寄存器中,即

    mov ebx, x
    mov ecx, y

现在ebxecx包含数组的第一个字节的地址。指令(在标签之后)

transfere:
    mov ecx, ebx

也不符合您(可能)的期望,即将数据从第一个数组复制到另一个数组。它所做的只是将存储在ebx中的值复制到ecx中,因此这将丢失第二个数组的地址。为了将位于ebx指向的地址上的单词复制到位于ecx指向的地址上的单词,您需要做些什么strong>是

    mov dx, [ebx]
    mov [ecx], dx

mov指令只能有一个内存操作数,因此我们首先将单词复制到字寄存器中,在这种情况下为dx,然后将dx复制到内存中ecx指向的地址,我们需要使用字寄存器(16位),而不是双字寄存器,例如edx。完成此操作后,我们需要使ecxebx指向下一个字,该字是当前地址之后的2个字节。所以我们做

    add ebx, 2
    add ecx, 2

否则该循环就可以了,但是紧随其后的指令需要删除:

    mov [y], ecx

这会将ecx(一个内存地址)的值复制到数组y中,这将导致打印垃圾(因为此地址被解释为4个字符)。 这样完成的程序如下所示:

section .text

global _start

_start:

    mov     eax, 5
    mov     ebx, x
    mov     ecx, y
transfere:
    mov     dx, [ebx]
    mov     [ecx], dx
    add     ebx, 2
    add     ecx, 2
    dec     eax
    jnz     transfere

    mov     eax, 4
    mov     ebx, 1
    mov     ecx, y
    mov     edx, 10
    int     0x80

    mov     eax, 1
    int     0x80

section .data

    x times 5 dw '5'
    y times 5 dw 0

这是一个较短的版本,它使用较少的寄存器(开始和结束与上述程序相同,因此省略):

_start:

    mov     eax,5
transfere:
    mov     bx, [x + eax*2 - 2]
    mov     [y + eax*2 - 2], bx
    dec     eax
    jnz     transfere

    ...