Попытка построить массив в ARM Assembly - PullRequest
0 голосов
/ 28 июня 2018

Я изучаю сборку ARM и пытаюсь построить массив, но он печатает только последнее слово, которое я напишу, как в следующем примере:

* ** 1003 тысяча два * Пример

Я пытался изменить способ увеличения индекса, но у меня был тот же результат. Может кто-нибудь показать мне, что я делаю не так? Или покажи мне пример?

Код (простите за комментарии, на португальском):


.global _start

.equ TAM, 100 
.set end, 0

_start:

    mov R0, #0

Loop:
    cmp R5, #3
    beq done

    ldr R3, =i
    lsl R4, R5, #2
    add R4, R4, R3

    mov     r0, #1                  @ Comando de saida
    ldr     r1, =msg_prod_nome      @ Endereco da mensagem
    ldr     r2, =len_prod_nome      @ Tamanho mensagem a ser escrita
    mov     r7, #4                  @ Sinaliza a saída no console
    svc     0x055

    mov     r0, #0                  @ Comando de entrada
    ldr     r1, =produto_nome       @ Endereco da mensagem
    ldr     r2, =TAM        @ Tamanho maximo a ser lido
    mov     r7, #3                  @ Sinaliza a entrada no console
    svc     #0x55

    str     r1, [R4]

    add R5, R5, #1

    b Loop

done:
    mov R5, #0

readloop:
    cmp R5, #3
    beq readdone
    ldr R3, =i
    lsl R4, R5, #2
    add R4, R4, R3

    mov     r0, #1                  @ Comando de saida      @ Endereco da mensagem
    ldr     r1, [R4]
    ldr     r2, =TAM 
    mov     r7, #4                  @ Sinaliza a saída no console
    svc     0x055

    mov     r0, #1                  @ Comando de saida
    ldr     r1, =quebra_linha   @ Endereco da mensagem
    ldr     r2, =len                @ Tamanho mensagem a ser escrita
    mov     r7, #4                  @ Sinaliza a saída no console
    svc     0x055

    add R5, R5, #1

    b readloop
@ ------------------------------

readdone:
    mov     r0, #0
    mov     r7, #1
    svc     #0x55

i:
    .skip 100

produto_nome:
    .skip TAM

quebra_linha:
    .ascii "\r\n\r"
    len = . - quebra_linha


1 Ответ

0 голосов
/ 28 июня 2018

Может кто-нибудь показать мне, что я делаю не так?

Вы не использовали отладчик: http://idownvotedbecau.se/nodebugging/

Программирование в сборке без отладчика похоже на попытку собрать робота с завязанными глазами. Это возможно, но это занимает гораздо больше времени (от 10 до 100 раз сложнее, без шуток), умения и усилий.

Я не могу найти, каков ваш «оружейный» на самом деле, и где у него есть некоторая документация, так что проверьте себя или обратитесь к поставщику ПО за документацией + помощь. Но для этого обязательно должен быть какой-то отладчик, иначе просто найдите другой симулятор / эмулятор ARM с разными инструментами, потому что нет смысла изучать сборку ARM на враждебной платформе. Машинный код, который вы изучите в другом симуляторе ARM, будет в основном таким же (хотя службы, специфичные для платформы, такие как svc 0x55, могут быть совершенно разными и, возможно, некоторый синтаксис в ассемблере, как в мире PC x86, существует около 10 различных синтаксисов для ассемблера и иногда это может сбивать с толку, если источник не содержит информации о том, какой синтаксис он использует).


Это был ответ на ваш вопрос, ниже приведены некоторые примечания о вашем коде:

    cmp R5, #3

Если ваша платформа явно не указывает состояние значений после выполнения вашего кода, использование неинициализированных регистров является плохой практикой. Я не проверял вашу конкретную платформу, но обычно в таких симуляторах обучения регистры обнуляются, но это не гарантируется, т. Е. Создатели симулятора должны были бы вложить в них случайные значения, чтобы на ранних этапах узнать людей, как это работает. на самом деле.

Так что этот сравнивает неизвестное значение в R5 с 3.

    str     r1, [R4]

Если svc не изменяет значение в регистрах (вероятно, нет, догадываясь по экрану вывода, но вы должны знать ), это будет сохранено в памяти по адресу R4 символьное значение (адрес памяти) produto_nome.

Итак, после того, как ваш первый [входной] цикл завершен (который называется Loop, в отличие от цикла печати, который называется readloop ... Вы, вероятно, должны рассмотреть карьеру в бизнесе обфускатора, я вижу здесь некоторый талант ) содержимое памяти в разделе .data выглядит примерно так (вручную «разбирают» обратно в исходный код, но вы должны попытаться проверить в отладчике вашего симулятора, как вы можете просматривать фактическое содержимое памяти, одновременно переходя по одной инструкции) :

i:
   .word  produto_nome
   .word  produto_nome
   .word  produto_nome

produto_nome:
   .ascii "your last input", "remains of previous longer inputs"
   .skip <remaining bytes to 100>
     @ ^ = maybe zeroes, if your platform zeroes .data segment

quebra_linha:
   .ascii "\r\n\r"  @ on any decent platform "\n" is enough for newline
     @ (DOS and Windows are different, but those are obsolete and dead)

Как вы можете видеть, в памяти есть только последний вход в качестве завершенного (и даже там у вас нет никакого способа узнать, где он заканчивается), предыдущие входы перезаписываются им (вы можете попробовать, введя "aaaaa", "bbb", "c" и посмотрите, что получится, это также покажет вам, является ли символ новой строки или нулевой терминатор частью ввода или нет, если ввод - просто чистые строковые данные, то результат должен быть " cbbaa».

В ассемблере у вас есть только физическая память в чипе, поэтому она не растет динамически, как обычные переменные в более высоких языках программирования.

Вам нужно будет решить, как вы хотите, чтобы ваш массив строк хранился в памяти, так как есть много опций:

  • самая несжатая компактная форма, такая как "aaaaa\0bbb\0c\0", которая занимала бы только 12 байтов, но трудно получить доступ к «случайному» индексу i , так как вы должны каждый раз искать весь контент с самого начала и считать завершающие нули, пока вы не найдете начало i -ой строки (кстати, вам не нужен «произвольный» доступ в цикле печати, поскольку вы печатаете все значения последовательно, поэтому эта форма является разумным выбором для текущей код, но это будет немного медленнее для приложения с произвольным доступом, но он будет использовать меньше памяти ... решения, решения ... Обычно эта форма используется для таких вещей, как аргументы командной строки, но есть дополнительный массив указателей, указывая на начало каждой строки, чтобы вы получили как хорошую производительность, так и компактное использование памяти)
  • самая простая форма, резервирующая 3x100 байт, поэтому каждая входная строка начинается с адреса «массив + i * 100».
  • массив указателей 3x4 байта, как у вас сейчас, но вы также должны зарезервировать место для хранения ввода в другом месте, вероятно, снова 3x100 байтов, как в предыдущем случае, и хранить указатели на это пространство, а не фиксированное значение produto_nome.

Самое простое решение для новичка - использовать большой буфер памяти N * TAM и вычислять указатели на строки как array_buffer + i * TAM.

Также, если вы измените TAM на 128 вместо 100 (попробуйте использовать в сборке вместо «округленных» значений, таких как 128, не округленные значения, такие как 100, в некоторых ситуациях намного сложнее обрабатывать для компьютера. ... о, кстати, если вы думаете, что "100" округлено, а "128" нет, попробуйте просмотреть их в двоичном виде, вот как их видит компьютер ...), вы можете умножить i, просто сдвинув его влево 7 раз (т.е. lsl R4, R5, #7), чтобы получить значение i*128.

Так что я бы изменил эти сдвиги в вашем коде, тогда память после метки i: должна быть зарезервирована как .skip TAM*3 (если ваш ассемблер способен вычислять выражения во время компиляции, в противном случае вам придется использовать .skip 384 ), и сделайте входное чтение, чтобы нацелить память массива напрямую, без дополнительного буфера produto_nome, чтобы вам не нужно было копировать 128 байтов строки в буфер массива после svc 0x55.

Также проверьте, что именно делает служба mov r0, #0, завершает ли она строку нулем или нет, и возвращает ли она длину где-нибудь или нет. И вам, вероятно, следует печатать только введенную длину данных, а не весь буфер TAM (если только служба печати #1 не завершает работу после нулевого терминатора или чего-то еще, но выглядит как обычная служба write(...), т.е. она будет выводиться в полный буфер консоли, включая ненужную после ввода текста пользователем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...