Встроенный ASM на C, скомпилированный с помощью MinGW / GCC с использованием -masm = intel: undefined reference

Я много искал примеры использования встроенного ASM и видел несколько разных подходов.

При компиляции я использовал параметр -masm = intel. Насколько я понимаю, при использовании этой опции вы можете просто написать встроенный ASM, как и с синтаксисом Intel.

Я также видел подходы, в которых люди используют ".intel_syntax"

Когда я компилирую, я получаю следующее сообщение.

    i586-mingw32msvc-gcc -masm=intel -o KDOS.exe KDOS.c
    /tmp/ccVIXhRF.o:KDOS.c:(.text+0x5f): undefined reference to `address'
    /tmp/ccVIXhRF.o:KDOS.c:(.text+0x6a): undefined reference to `ipAddr'
    /tmp/ccVIXhRF.o:KDOS.c:(.text+0x79): undefined reference to `csAddr'
    /tmp/ccVIXhRF.o:KDOS.c:(.text+0x11d): undefined reference to `address'
    collect2: ld returned 1 exit status

Я искал решение, но не могу его найти. Я видел потоки, в которых говорилось, что вы не можете передавать переменные C во встроенный ASM, но я также видел некоторые вещи, говорящие о том, что есть обходные пути. Они не совсем подходили к тому, что я делал, поэтому я не был уверен, что с ними делать. Извините, если это очевидный ответ, но это мой первый раз, когда я использую встроенный ASM, гораздо меньше шуток с преобразованием синтаксиса.

Вот мой код. Я работаю над книгой, и это пример кода в ней. Он не был скомпилирован с помощью gcc в книге, поэтому мне нужно преобразовать его в синтаксис Intel, потому что он, очевидно, мне нужен для работы в Windows. Это моя модифицированная версия кода:

// KDOS.c
// Chapter 2

#include<stdio.h>

#define WORD unsigned short

#define IDT_001_ADDR    0        //start address of first IVT vector
#define IDT_255_ADDR    1020     //start address of last IVT vector
#define IDT_VECTOR_SZ   4        //size of each IVT Vector (in bytes)

#define BP    __asm{ int 0x3 }    //break point

void main()
{
    WORD csAddr;                 //Code segment of given interrupt
    WORD ipAddr;                 //Starting IP for given interrupt
    short address;               //address in memory (0-1020)
    WORD vector;                 //IVT entry ID (i.e., 0..255)
    char dummy;                  //strictly to help pause program execution

    vector = 0x0;

    printf("\n---Dumping IVT from bottom up---\n");
    printf("Vector\tAddress\t\n");

    for
     (
        address=IDT_001_ADDR;
        address<=IDT_255_ADDR;
        address=address+IDT_VECTOR_SZ,vector++
    )
    {
        printf("%03d\t%08p\t",vector,address);

        //IVT starts at bottom of memory, so CS is alway 0x0

        __asm__
        (
           ".intel_syntax;"
           "PUSH ES;"
           "MOV AX, 0;"
           "MOV ES,AX;"
           "MOV BX,address;"
           "MOV AX,ES:[BX];"
           "MOV ipAddr,AX;"
           "INC BX;"
           "INC BX;"
           "MOV AX,ES:[BX];"
           "MOV csAddr,AX;"
           "POP ES;"
    );
        printf("[CS:IP]=[%04X,%04X]\n",csAddr,ipAddr);
    }

    printf("press [ENTER] key to continue:");
    scanf("%c",&dummy);

    printf("\n---Overwrite IVT from top down---\n");

    /*
        Program will die somwhere around 0x4*
        Note: can get same results via DOS debug.exe -e command
    */

    for
    (
        address=IDT_255_ADDR;
        address>=IDT_001_ADDR;
        address=address-IDT_VECTOR_SZ,vector--
    )
    {
        printf("Nulling %03d\t%08p\n",vector,address);
         __asm__
        (
        ".intel_syntax;"
            "PUSH ES;"
            "MOV AX,0;"
            "MOV ES,AX;"
            "MOV BX,address;"
            "MOV ES:[BX],AX;"
            "INC BX;"
            "INC BX;"
            "MOV ES:[BX],AX;"
            "POP ES;"
    );
    }
    return;
}/*end main()------------------------------------------------------------*/

Любая помощь будет принята с благодарностью. Еще раз приношу свои извинения, если что-то очевидно.


person econsteve    schedule 15.03.2013    source источник
comment
Я сам не пробовал, но, похоже, их следует рассматривать как аргументы - ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#ss5.2   -  person SpacedMonkey    schedule 15.03.2013
comment
Этот вопрос был бы намного лучше, если бы вы сократили пример кода до минимального фрагмента кода, который показывает проблему.   -  person Vicky    schedule 03.05.2013


Ответы (1)


На самом деле вы можете передать C аргументов встроенному asm. Но вы должны определить его после части кода asm.

В вашем случае может сработать что-то вроде этого (вы должны добавить -masm=intel в командную строку gcc):

asm(
    ".intel_syntax noprefix;\n\t"
    ...
    "MOV BX,%[address];\n\t"
    ...
    ".intel_syntax prefix;\n\t"
    :: [address] "m" address, ...
    : "AX", "BX", /* all changed registers to inform compiler to save them if needed */
);

См. Примеры в аналогичном вопросе..

person TrueY    schedule 03.05.2013