簡體   English   中英

將AT&T內聯匯編程序用於GCC

[英]Using AT&T inline assembler for GCC

我正在編寫一個簡單但有點具體的程序:

目的:根據階乘計算數字
要求:所有計算都必須在gcc內聯asm上完成(at&t語法)

源代碼:

#include <iostream>

int main()
{
        unsigned n = 0, f = 0;

        std::cin >> n;

        asm
        (
                "mov %0, %%eax \n"
                "mov %%eax, %%ecx \n"
                "mov 1, %%ebx \n"
                "mov 1, %%eax \n"
                "jmp cycle_start\n"
                "cycle:\n"
                "inc %%ebx\n"
                "mul %%ebx\n"
                "cycle_start:\n"
                "cmp %%ecx, %%eax\n"
                "jnz cycle\n"
                "mov %%ebx, %1 \n":

                "=r" (n):
                 "r" (f)

       );

       std::cout << f;

       return 0;
}

此代碼導致SIGSEV。

使用intel asm語法的完全相同的程序( http://pastebin.com/2EqJmGAV )可以正常工作。 為什么我的“ AT&T程序”失敗了,我該如何解決?

#include <iostream>

int main()
{
   unsigned n = 0, f = 0;

   std::cin >> n;

   __asm
   {
      mov eax, n

      mov ecx, eax
      mov eax, 1
      mov ebx, 1
      jmp cycle_start

      cycle:

      inc ebx
      mul ebx

      cycle_start:

      cmp eax, ecx
      jnz cycle

      mov f, ebx
   };
   std::cout << f;

   return 0;
}

UPD:推入堆棧並還原使用過的寄存器將得到相同的結果:SIGSEV

您的輸入和輸出方式錯誤。

所以,從改變開始

            "=r" (n):
             "r" (f)

至:

             "=r" (f) :
             "r" (n)

然后,我懷疑您將要告訴編譯器有關Clobbers(您正在使用的不是輸入或輸出的寄存器):

因此添加:

  : "eax", "ebx", "ecx" 

在以上兩行之后。

我個人將做出其他一些更改:

  1. 使用本地標簽( 1:2:等),這樣可以復制代碼而無需“重復標簽”。
  2. 使用%1代替%%ebx這樣,您就不會使用額外的寄存器。
  3. %0直接移動到%%ecx 要裝載1%%eax兩個指令后,所以有它得到了在做什么樣的目的%%eax

[現在,我寫的太多了,其他人先回答了...]

編輯:而且,正如安東指出,需要$1加載常數1, 1是指從地址1,讀不很好地工作,而且最有可能是你的問題的原因

希望沒有要求,只使用gcc inline asm來解決它。 您可以使用nasm轉換您的AT&T示例,然后使用objdump進行反匯編並查看正確的語法。

我似乎還記得,如果您的意思是字面常量而不是內存引用mov 1,%eax那么mov 1,%eax應該是mov $1,%eax

@MatsPetersson的答案對於內聯程序集與編譯器(填充/輸入/輸出寄存器)的交互非常有用。 我一直在關注您得到SIGSEGV的原因,並且讀取地址1確實可以回答問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM