2013-03-15 68 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例子。