2015-12-19 217 views
2

我試圖編譯這個x86 assembly code在x64上的Debian:鏈接彙編程序:錯誤 「未定義的參考`printf的'」

BITS 32 

%include 'training.s' 

global main 
extern exit  

; =============================================== 
section .text 

main: 
    ; The program begins here: 

    call read_hex  
    mov  edx,eax 
    call read_hex  
    add  eax,edx 
    add  eax,eax 
    inc  eax   

    call print_eax 

    ; Exit the process: 
    push 0 
    call exit 

我得到這些錯誤:

~$nasm -f elf -g 0_strange_calc.asm && ld -o 0_strange_calc 0_strange_calc.o 
    ld: i386 architecture of input file `0_strange_calc.o' is incompatible with i386:x86-64 output 
    ld: warning: cannot find entry symbol _start; defaulting to 00000000004000b0 
    0_strange_calc.o:training.s:25: undefined reference to `printf' 
    0_strange_calc.o:training.s:35: undefined reference to `printf' 
    0_strange_calc.o:training.s:45: undefined reference to `printf' 
    0_strange_calc.o:training.s:56: undefined reference to `read' 
    0_strange_calc.o:training.s:77: undefined reference to `scanf' 
    0_strange_calc.o:training.s:97: undefined reference to `scanf' 
    0_strange_calc.o:training.s:108: undefined reference to `printf' 
    0_strange_calc.o:training.s:129: undefined reference to `printf' 
    0_strange_calc.o:training.s:137: undefined reference to `printf' 
    0_strange_calc.o:0_strange_calc.asm:50: undefined reference to `exit' 




~$ yasm -f elf64 0_strange_calc.asm 
    ~$ gcc -m32 -nostdlib -nostdinc 0_strange_calc.o -o 0_strange_calc 
    /usr/bin/ld: i386:x86-64 architecture of input file `0_strange_calc.o' is incompatible with i386 output 
    /usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 00000000080480c0 
    0_strange_calc.o: In function `no symbol': 
    0_strange_calc.asm:(.text+0x8): undefined reference to `printf' 
    0_strange_calc.asm:(.text+0x19): undefined reference to `printf' 
    0_strange_calc.asm:(.text+0x2a): undefined reference to `printf' 
    0_strange_calc.asm:(.text+0x39): undefined reference to `read' 
    0_strange_calc.asm:(.text+0x5b): undefined reference to `scanf' 
    0_strange_calc.asm:(.text+0x7a): undefined reference to `scanf' 
    0_strange_calc.asm:(.text+0x89): undefined reference to `printf' 
    0_strange_calc.asm:(.text+0xa8): undefined reference to `printf' 
    0_strange_calc.asm:(.text+0xb9): undefined reference to `printf' 
    0_strange_calc.o: In function `main': 
    0_strange_calc.asm:(.text+0xdb): undefined reference to `exit' 
    collect2: error: ld returned 1 exit status 

這是我的0_strange_calc.o轉儲:

~$ objdump -M intel -d 0_strange_calc.o 

0_strange_calc.o:  file format elf64-x86-64 


Disassembly of section .text: 

0000000000000000 <main-0xc2>: 
    0: 60      (bad) 
    1: 50      push rax 
    2: 68 00 00 00 00   push 0x0 
    7: e8 00 00 00 00   call c <main-0xb6> 
    c: 83 c4 08    add esp,0x8 
    f: 61      (bad) 
    10: c3      ret  
    11: 60      (bad) 
    12: 50      push rax 
    13: 68 00 00 00 00   push 0x0 
    18: e8 00 00 00 00   call 1d <main-0xa5> 
    1d: 83 c4 08    add esp,0x8 
    20: 61      (bad) 
    21: c3      ret  
    22: 60      (bad) 
    23: b8 00 00 00 00   mov eax,0x0 
    28: 50      push rax 
    29: e8 00 00 00 00   call 2e <main-0x94> 
    2e: 83 c4 04    add esp,0x4 
    31: 61      (bad) 
    32: c3      ret  
    33: 60      (bad) 
    34: 51      push rcx 
    35: 57      push rdi 
    36: 6a 00     push 0x0 
    38: e8 00 00 00 00   call 3d <main-0x85> 
    3d: 83 c4 0c    add esp,0xc 
    40: 31 d2     xor edx,edx 
    42: c6 04 07 00    mov BYTE PTR [rdi+rax*1],0x0 
    46: 61      (bad) 
    47: c3      ret  
    48: 55      push rbp 
    49: 89 e5     mov ebp,esp 
    4b: 83 ec 04    sub esp,0x4 
    4e: 53      push rbx 
    4f: 51      push rcx 
    50: 52      push rdx 
    51: 8d 5d fc    lea ebx,[rbp-0x4] 
    54: 53      push rbx 
    55: 68 00 00 00 00   push 0x0 
    5a: e8 00 00 00 00   call 5f <main-0x63> 
    5f: 83 c4 08    add esp,0x8 
    62: 8b 03     mov eax,DWORD PTR [rbx] 
    64: 5a      pop rdx 
    65: 59      pop rcx 
    66: 5b      pop rbx 
    67: c9      leave 
    68: c3      ret  
    69: 55      push rbp 
    6a: 89 e5     mov ebp,esp 
    6c: 83 ec 04    sub esp,0x4 
    6f: 8d 5d fc    lea ebx,[rbp-0x4] 
    72: 60      (bad) 
    73: 53      push rbx 
    74: 68 00 00 00 00   push 0x0 
    79: e8 00 00 00 00   call 7e <main-0x44> 
    7e: 83 c4 08    add esp,0x8 
    81: 61      (bad) 
    82: 8b 03     mov eax,DWORD PTR [rbx] 
    84: c9      leave 
    85: c3      ret  
    86: 60      (bad) 
    87: 56      push rsi 
    88: e8 00 00 00 00   call 8d <main-0x35> 
    8d: 83 c4 04    add esp,0x4 
    90: 61      (bad) 
    91: c3      ret  
    92: 60      (bad) 
    93: b9 20 00 00 00   mov ecx,0x20 
    98: d1 c0     rol eax,1 
    9a: 89 c2     mov edx,eax 
    9c: 83 e2 01    and edx,0x1 
    9f: 51      push rcx 
    a0: 50      push rax 
    a1: 52      push rdx 
    a2: 68 00 00 00 00   push 0x0 
    a7: e8 00 00 00 00   call ac <main-0x16> 
    ac: 83 c4 08    add esp,0x8 
    af: 58      pop rax 
    b0: 59      pop rcx 
    b1: e2 e5     loop 98 <main-0x2a> 
    b3: 68 00 00 00 00   push 0x0 
    b8: e8 00 00 00 00   call bd <main-0x5> 
    bd: 83 c4 04    add esp,0x4 
    c0: 61      (bad) 
    c1: c3      ret  

00000000000000c2 <main>: 
    c2: e8 81 ff ff ff   call 48 <main-0x7a> 
    c7: 89 c2     mov edx,eax 
    c9: e8 7a ff ff ff   call 48 <main-0x7a> 
    ce: 01 d0     add eax,edx 
    d0: 01 c0     add eax,eax 
    d2: 40 e8 28 ff ff ff  rex call 0 <main-0xc2> 
    d8: 6a 00     push 0x0 
    da: e8 00 00 00 00   call df <main+0x1d> 

它似乎已成功轉換爲x64 asm,其他簡單e代碼我編譯和鏈接沒有問題。我究竟做錯了什麼?我該如何解決它?

+0

我認爲錯誤信息是很清楚的:'i386架構與i386的不兼容,可以使用此命令行來完成: x86-64'。 – m0skit0

+0

它也像它想你的入口點被命名爲「啓動」,而不是「主」 –

回答

6

發現你有幾個選項

  • 使用LD鏈接到最終的可執行
  • 使用GCC鏈接到最終的可執行

使用LD方法

您的命令行使用LD,不幸的是存在很多問題。第一:

LD:輸入文件`0_strange_calc.o」 i386架構是與I386不相容:x86-6

您是在64位的Debian,試圖以產生32位可執行文件。-f elfNASM命令行生成32位ELF(-f elf64生成64位對象)。您的LD命令行默認情況下會嘗試生成64位可執行文件,因此會給出上述錯誤。您可以強制LD通過將-m elf_i386選件添加到的LD的命令行來生成32位可執行文件。

ld:warning:無法找到條目符號_start;默認爲00000000004000b0

你應該告訴LD你的切入點是主要LD默認查找_start的入口點。您可以將-e main添加到LD命令行來解決該問題。

象這樣的錯誤提示你需要的Ç庫(其中的printf存在):

0_strange_calc.asm :(文字+ 0x8中):未定義的引用`printf的」

由於您的代碼不直接使用printf我只能假設這是training.s中的函數所要求的。爲了鏈接C庫,您需要將它添加到命令行中的.o文件之後。您可以在LD命令行上使用-lc執行此操作。您還需要特別告訴LD您需要使用哪種動態鏈接庫(在本例中爲32位)。在Debian的環境,通常是這樣的:-dynamic-linker /lib/ld-linux.so.2

所以你NASMLD線應該是這樣的:

nasm -f elf -g 0_strange_calc.asm 
ld -melf_i386 -e main -dynamic-linker /lib/ld-linux.so.2 -o 0_strange_calc 0_strange_calc.o -lc 

使用GCC方法

可以簡化鏈接到C庫通過使用GCC來鏈接你將對象文件轉換爲可執行文件。要構建32位可執行文件,你可以使用:

nasm -f elf -g 0_strange_calc.asm 
gcc -m32 0_strange_calc.o -o 0_strange_calc 

Ç庫和運行時刻有_start方法,做Ç啓動初始化並依次調用名爲主要功能恰好成爲你的程序集文件中的函數。 -m32告訴GCC您還鏈接到一個32位可執行文件。


特別注意事項

您可能還需要安裝Multlilib版本的gcc(和g ++,如果你願意的話),這樣就可以正確地構建和64上運行32位應用程序使用適當的C庫。

apt-get install gcc-multilib g++-multilib 

在基於Ubuntu系統,你需要使用:

sudo apt-get install gcc-multilib g++-multilib 
+0

這似乎編譯,但它不會產生任何輸出文件。我使用這個命令:'$ NASM -f精靈-g 0_strange_calc.asm'' 〜$ LD -melf_i386 -e主要-dynamic - 銜接/lib/ld-linux.so.2 -o strange_calc 0_strange_calc.o - lc' – Kaka

+0

@Kaka我給原來的命令行輸出(I固定它已經)到一個名爲'strange_calc'文件(不是'0_strange_calc')。這是我的錯誤。只需將其更改爲'LD -melf_i386 -e主要-dynamic - 銜接/lib/ld-linux.so.2 -o 0_strange_calc 0_strange_calc.o -lc'(只錯了輸出文件是事) –

+0

是的,它產生一個名爲「strange_calc」的文件。現在我設法運行它。該應用程序似乎沒有給出任何輸出,但我想這是預期的結果。謝謝 – Kaka

2

請注意,問題不在於asm代碼,而是缺少導入的函數。如果您閱讀 training.s,您將看到printeax以及其他方法的定義。而且你會發現其中的一些方法的使用external functionprintf這當然是不asm功能,但一些進口語言的lib

BITS 32 
extern printf 
extern exit 
extern scanf 
extern read 

所以爲了使其發揮作用 - 即尋找那些外部庫(你也在那裏警告你應該處理,但這不在這個範圍內)。您需要正確使用鏈接器。據Franknasm board你有兩個選擇

  1. 使用ld鏈接,但告訴它通過lc選擇使用c庫。即:ld -ld -o 0_strange_calc 0_strange_calc.o -lc。可以找到更多信息here

  2. 使用gcc接頭。

P.S 也代碼使用32bit注意您的計算機上生成一個警告,你可以使用64 bit並使用elf標誌。更多關於它,你可以在nasm docs

相關問題