передача массива в массив в сборке, получая странный вывод. Зачем? - PullRequest
0 голосов
/ 30 апреля 2019

я пытаюсь понять, как манипулировать массивами для класса, но даже код точно такой же, как и в материале поддержки, я получил эту проблему

на этом сайте есть код, который меня вдохновляет 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 Ответ

1 голос
/ 01 мая 2019

Первая проблема связана с инструкциями

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

, которые просто загрузят первые 32 бита массивов x и y в ebx и ecx соответственно.Я предполагаю, что вы хотите сделать, это загрузить адреса этих массивов в эти два регистра, то есть

    mov ebx, x
    mov ecx, y

Теперь ebx и ecx содержат адрес первых байтов массивов.Инструкция (после метки)

transfere:
    mov ecx, ebx

также не делает то, что вы (вероятно) ожидаете, а именно копировать данные из первого массива в другой.Все, что он делает, это копирует значение, хранящееся в ebx, в ecx, так что это потеряет адрес второго массива.Что нужно сделать, чтобы скопировать слово, расположенное по адресу, указанному ebx в слово, расположенное по адресу, указанному ecx, равно

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

(Инструкция mov может иметь только один операнд памяти, поэтому сначала мы копируем слово в регистр слов, в данном случае dx, а затем копируем dx в память, на которую указываетecx. Нам нужно использовать регистр слов (16 бит), а не регистр слов, такой как edx здесь).После того, как это сделано, нам нужно заставить ecx и ebx указывать на следующее слово, которое находится через 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

    ...
...