Недопустимая инструкция при выполнении вызова функции в RISC-V - PullRequest
0 голосов
/ 24 сентября 2018

Goodmorning,

Я пытаюсь написать простую программу на ассемблере для архитектуры RISC-V, в которой у меня есть простой main (_start), который выполняет вызов функции, который ничего не делает, и возвращает вызывающей стороне.

Код, который я написал, выглядит следующим образом:

.section .text
.global _start

test:
    lw a1, 0(sp)



    # ritorna al chiamante
    jr ra

_start:
    # push sullo stack
    addi sp, sp, -4

    li a1, 5

    # mette valore di ritorno sullo stack
    # salva a1 sullo stack
    sw a1, 0(sp)

    # chiamata a funzione
    jal ra, test

    # pop dallo stack
    addi sp, sp, +4

    li a6, 2

Для выполнения этой программы я запускаю:

$ riscv64-unknown-elf-as somma.s -o somma.o
$ riscv64-unknown-elf-ld somma.o -o somma.elf
$ spike pk somma.elf

В качестве вывода я получаю:

z  0000000000000000 ra 0000000000010090 sp 000000007f7e9b50 gp 0000000000000000
tp 0000000000000000 t0 0000000000000000 t1 0000000000000000 t2 0000000000000000
s0 0000000000000000 s1 0000000000000000 a0 0000000000000000 a1 0000000000000005
a2 0000000000000000 a3 0000000000000000 a4 0000000000000000 a5 0000000000000000
a6 0000000000000002 a7 0000000000000000 s2 0000000000000000 s3 0000000000000000
s4 0000000000000000 s5 0000000000000000 s6 0000000000000000 s7 0000000000000000
s8 0000000000000000 s9 0000000000000000 sA 0000000000000000 sB 0000000000000000
t3 0000000000000000 t4 0000000000000000 t5 0000000000000000 t6 0000000000000000
pc 0000000000010098 va 0000000000000000 insn       00000000 sr 8000000200046020
An illegal instruction was executed!

В этом случае у нас есть 2 в регистре a6, поэтому я предполагаю, что управление программой правильно возвращено вызывающей программе, так как последняя инструкция выполнена правильно, но я все равно получаю ошибку "Недопустимая инструкция былавыполнено!»Не могли бы вы дать мне несколько советов для решения этой проблемы?

Спасибо

1 Ответ

0 голосов
/ 15 октября 2018

Это одно из различий между программированием на C и сборкой: в C компилятор обрабатывает код входа / выхода функции для вас, в то время как при сборке вы должны обрабатывать его самостоятельно.В этом конкретном случае ваша _start функция не заканчивается на ret, и поэтому ее выполнение будет продолжаться после завершения функции.Поскольку это конец вашего двоичного файла, следующие байты, вероятно, являются недопустимой инструкцией (инструкция all-0 недопустима в RISC-V).

Функция _start представляет собой особый случай: whileбольшинство ABI RISC-V говорят, что можно возвращаться с _start, канонический _start никогда не вернется и вместо этого будет вызывать exit() напрямую.Лучшая ставка для _start - завершить ее с li a0, 0; call exit; ret.

...