Как использовать определения C в ассемблере ARM

Как я могу использовать внешние определения, такие как LONG_MIN и LONG_MAX, в коде ассемблера ARM?

Допустим, my_arm.h выглядит так:

int my_arm(int foo);

Скажем, у меня есть my_main.c следующим образом:

...
#include <limits.h>   
#include "my_arm.h"
...
int main (int argc, char *argv[])
{
  int foo=0;
...
  printf("My arm assembler function returns (%d)\n", my_arm(foo));
...
}

И my_arm.s выглядит так:

  .text
  .align 2
  .global my_arm
  .type   my_arm, %function
my_arm:
    ...
    ADDS r1, r1, r2
    BVS overflow
    ...
overflow: 
    LDR r0, LONG_MAX @ this is probably wrong, how to do it correctly?
    BX lr @ return with max value

Предпоследняя строка, я не уверен, как правильно загрузить, я смутно помню, что где-то читал, что мне нужно было определить LONG_MAX в .global, но больше не могу найти ссылку на рабочий пример.

Я компилирую с помощью arm-linux-gnueabi-gcc версии 4.3.2.

==================

ОБНОВЛЕНИЕ: Цените предложения! К сожалению, у меня все еще проблемы с синтаксисом.

Сначала я сделал небольшой заголовочный файл mylimits.h (пока в том же каталоге, что и .S)

#define MY_LONG_MIN 0x80000000

в my_arm.S я добавил следующее:

...
.include "mylimits.h"
...
ldr r7, =MY_LONG_MIN @ when it was working it was ldr r7, =0x80000000
...

Две проблемы с этим подходом.

Первая самая большая проблема: символ MY_LONG_MIN не распознается... так что что-то все равно не так

Во-вторых: синтаксис для .include не позволяет мне включать <limits.h>, я должен был бы добавить это в mylimits.h, кажется немного неуклюжим, но я полагаю, это нормально :)

Любые указатели?

У меня есть доступ к Руководству разработчика систем ARM Designing and Optimizing System Software[2004] и Справочному руководству по архитектуре ARM[2000], однако моя цель — XScale-IXP42x Family rev 2 (v5l).


person Sint    schedule 19.06.2010    source источник
comment
Не знаю насчет ARM, но если вы в mips, переименовав расширение в .S, C предварительно обработает файл.   -  person Tom    schedule 19.06.2010
comment
используйте #include не .include и .S не .s, как сказано в ответе. Таким образом, вы используете функцию gcc, и все должно пройти, как для моих тестов в x86, кроме сборки, которая, конечно, отличается.   -  person ShinTakezou    schedule 07.07.2010


Ответы (5)


Часто расширение файла в нижнем регистре .s подразумевает, что ассемблер не должен проходить через препроцессор c, тогда как расширение в верхнем регистре .S подразумевает, что это необходимо. Однако ваш компилятор должен следовать этому соглашению (обычно это делают порты gcc), поэтому проверьте его документацию.

(EDIT: обратите внимание, что это означает, что вы можете использовать директивы #include, но помните, что большинство файлов, которые вы будете включать, обычно не будут действительным ассемблером (если только они не состоят полностью из #defineitions), поэтому вам, возможно, придется написать свой собственный заголовок, который )


редактировать 5 лет спустя:

Обратите внимание, что компилятор armcc v5 следует этому поведению в Linux... но не в Windows.

person James    schedule 19.06.2010
comment
Если используется набор инструментов GCC, макрос __ASSEMBLER__ определяется при предварительной обработке файлов сборки. Это можно использовать, чтобы помочь файлу .h работать в любом мире (asm и C), если это необходимо. Но, возможно, лучше всего по возможности разделить элементы, которые должны работать в обоих мирах, в отдельные заголовки. Хотя для чего-то вроде LONG_MAX, определенного в стандартном заголовке, у вас нет большого контроля над... - person Michael Burr; 19.06.2010
comment
Да, со стандартными заголовками толку от этого мало! (За исключением иногда заголовков архитектуры, которые определяют такие вещи, как адреса ввода-вывода с отображением памяти, которые предназначены для этой цели) - person James; 20.06.2010

Если вы используете gcc и его ассемблер, это просто: назовите файл с конечным .S, затем добавьте в начале #include <limits.h> и используйте везде, где вам нужна константа, например. ldr r0, SOMETHING; Я провел тесты с x86, так как это то, что у меня есть, но то же самое работает, поскольку это функция gcc.

person ShinTakezou    schedule 02.07.2010

В итоге я сделал следующее:

в my_main.c

#include <limits.h>
...
int my_LONG_MAX=LONG_MAX;

затем в my_arm.S

ldr r8, =my_LONG_MAX 
ldr r10, [r8] 

Это выглядит запутанным, и это так (плюс преимущества переносимости при таком подходе сомнительны).

Должен быть способ получить доступ к LONG_MAX непосредственно в сборке. Такой способ я бы с радостью принял как полный ответ.

person Sint    schedule 28.06.2010
comment
если кто-то хочет добавить лучшее решение, я с радостью приму этот ответ - person Sint; 01.07.2010
comment
Это очень некрасиво. Почему вы все равно пытаетесь использовать определения, связанные с размером типа, с ассемблером? Если у вас единая архитектура (присущая asm), то просто пишите константу буквально. Это не изменится! - person R.. GitHub STOP HELPING ICE; 04.07.2010
comment
О, это ужасно, я признаю. :) Это реализация библиотечной функции. Если бы у меня был свой путь, я бы написал это как константу напрямую. - person Sint; 05.07.2010

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

person old_timer    schedule 20.06.2010

используйте --cpreproc для опции armasm и добавьте

#include "my_arm.h"

в моих руках.

это работает для Keil ARM

person netawater    schedule 27.10.2015