La liaison d'un programme en assembleur: message d'erreur “undefined reference to `printf'”
Je suis en train de compiler ce code assembleur x86 sur x64 Debian :
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
J'obtiens ces erreurs:
~$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
C'est mon dump de 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>
Il semble avoir été converti avec succès en x64 asm, l'autre simple code que j'avais compilé et lié sans problèmes. Ce que je fais mal? Et comment puis-je résoudre ce problème?
- Je pense que le message d'erreur est assez clair:
i386 architecture is incompatible with i386:x86-64
. - Aussi, on dirait qu'il veut de votre point d'entrée pour être nommé "start" plutôt que "principal"
Vous devez vous connecter pour publier un commentaire.
Vous avez un couple d'options
À l'aide de LD Méthode
Vos lignes de commande utilisation LD, malheureusement, qui présente un certain nombre de problèmes. La première:
Vous êtes sur une version 64 bits de Debian, en essayant de produire un exécutable 32 bits.
-f elf
sur le MSNA ligne de commande génère 32 bits ELF (-f elf64
générer 64 bits des objets). Votre LD ligne de commande est par défaut en essayant de générer un 64-bit exécutable ainsi, l'erreur ci-dessus est donné. Vous pouvez forcer LD pour générer un exécutable 32 bits en ajoutant le-m elf_i386
option pour LD's en ligne de commande.Vous devriez dire à LD que votre point d'entrée est principal . LD par défaut à la recherche d'un point d'entrée de _start. Vous pouvez ajouter
-e main
à la LD ligne de commande pour résoudre ce problème.Erreurs de ce type de suggérer vous avez besoin de la C de la bibliothèque (où printf existe):
Depuis votre code n'utilise pas printf directement, je ne peux que supposer que ce qui est requis par les fonctions dans
training.s
. Afin de créer un lien dans le C bibliothèque, vous devez l'ajouter après la.o
fichiers dans votre ligne de commande. Vous pouvez faire cela avec-lc
sur votre LD ligne de commande. Vous aurez également besoin de dire LD précisément ce que l'éditeur de liens dynamiques de la bibliothèque, vous aurez besoin d'utiliser (Dans ce cas, un 32-bit). Dans un environnement Debian qui normalement ressembler à:-dynamic-linker /lib/ld-linux.so.2
De sorte que votre MSNA et LD lignes devrait ressembler à ceci:
À l'aide de GCC Méthode
Vous pouvez simplifier la reliant à C bibliothèque à l'aide de GCC pour vous un lien à l'objet de votre fichier pour un fichier exécutable. Pour construire un exécutable 32 bits, vous pouvez utiliser:
La C de la bibliothèque et de la durée de fonctionnement est un _start méthode qui ne C de démarrage de l'initialisation et l'appelle à son tour une fonction appelée principal qui se trouve être la fonction dans votre fichier d'assemblage.
-m32
dit GCC vous êtes également un lien à un fichier exécutable 32 bits.Considérations Spéciales
Vous pouvez également besoin d'installer le Multlilib versions de gcc (et g++, si vous le souhaitez), de sorte que vous pouvez construire et exécuter des applications 32 bits sur 64 bits Debian à l'aide de la C bibliothèques. Qui peut être fait avec cette ligne de commande:
Sur Ubuntu systèmes basés sur, vous devrez utiliser:
strange_calc
(pas0_strange_calc
). C'est une erreur de ma part. Il suffit de changer àld -melf_i386 -e main -dynamic-linker /lib/ld-linux.so.2 -o 0_strange_calc 0_strange_calc.o -lc
(Le fichier de sortie était la seule chose qui était faux)print_eax
fonctionne depuis il ne fait pas partie du code. Mais si vous êtes de liaison et d'obtenir un exécutable, l'impression d'être incorrect serait probablement préférable de poser une autre question si vous ne pouvez pas le résoudre.Noter que le problème n'est pas le
asm
code mais manque une fonction importée. Si vous lisezla formation.s vous verrez la définition de
printeax
et d'autres méthodes. En outre, vous verrez que certains de ceux qui l'utilisation d'une méthodeexternal function
commeprintf
qui n'est évidemment pasasm
fonction, mais l'importation de certains de langue libAfin de le faire fonctionner - je.e de trouver ces libs externes ( vous avez également en garde que vous devez gérer, mais c'est hors de ce champ d'application). Vous devez utiliser l'éditeur de liens correctement. Selon
Frank
à la msna conseil vous avez deux optionsutiliser le
ld
de l'éditeur de liens, mais dites lui d'utiliserc
lib vialc
options. j'.e:ld -ld -o 0_strange_calc 0_strange_calc.o -lc
. Plus d'informations peuvent être trouvées iciutiliser le
gcc
de l'éditeur de liens.P. S
Notez que le code utilise
32bit
qui sur votre ordinateur produire un avertissement que vous pouvez utiliser64 bit
et que vous utilisezelf
drapeau. Plus sur ce que vous pouvez trouver à la msna docs