2013-03-15 130 views
3

我一直在寻找使用内联ASM的例子,我已经看到了几种不同的方法。C中的内联ASM,使用“-masm = intel”编译为MinGW/GCC:“undefined reference”

编译时我已经用-masm = intel选项了。据我了解,使用此选项时,您可以像使用intel语法一样编写内联ASM。

我也看到了其中我编译时收到以下消息的人使用“.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()------------------------------------------------------------*/ 

任何帮助将不胜感激。如果它是明显的,我再次表示歉意。

+0

我没有尝试过这个我自己,但它似乎应该被视为参数 - http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#ss5.2 – SpacedMonkey 2013-03-15 17:24:41

+0

这个问题如果你将你的代码示例减少到显示该问题的最小代码,它会更好。 – Vicky 2013-05-03 11:17:38

回答

2

实际上,您可以将C参数传递给内联asm。但是你必须在asm代码部分后面定义它。

你的情况是这样的可以工作(您应该添加-masm=intelgcc的命令行):

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 */ 
); 

请参阅在similar question例子。