2017-07-23 5 views
0

Pour certains contexte, je suis assez nouveau à l'assembleur, et mon assembleur de choix est NASM. Pour mon premier projet, j'utilise cygwin sur Windows 8.1, et j'ai essayé de convertir les informations de la seconde réponse sur cette question stackoverflow de 32 bits à 64 bits: How to write hello world in assembler under Windows?Je semble être incapable de résoudre cette erreur LD à partir d'un tutoriel WinAPI NASM

J'utilise gnu ld à la place de link.exe parce que le kernel32.Lib sur mon système semble être foiré, et je préfère de toute façon gnu ld. Donc, voici mon assembleur:

  global _main 
      extern [email protected] 
      extern [email protected] 
      extern [email protected] 

      section .text 
    _main 
      push   rbp 
      mov    rbp, rsp 
      sub    rsp, 4 

      ; hStdOut = GetStdHandle(STD_OUTPUT_HANDLE) 
      push   -11 
      call   [email protected] 
      mov    rbx, rax 

      ; WriteFile(hStdOut, message, length(message), &bytes, 0) 
      push   0 
      lea    rax, [rbp-4] 
      push   rax 
      push   (message_end - message) 
      push   message 
      push   rbx 
      call   [email protected] 

      mov    rsp, rbp 
      pop    rbp 

      ; ExitProcess(0) 
      push   0 
      call   [email protected] 

      ; 
      hlt 

    message   db  'Hello, World!', 10 
    message_end 

Quand je lance nasm -fwin64 ./test.asm il assemble sans erreur, seuls les avertissements de me laisser les noms sur les colons de l'étiquette.

La commande que je utilise pour créer un lien vers le WinAPI est

ld test.obj -lkernel32 --enable-stdcall-fixup /cygdrive/c/Windows/system32/kernel32.dll -o test.exe 

Cela me laisse

test.obj:./test.asm:(.text+0x1c): relocation truncated to fit: R_X86_64_32 against `.text' 

Donc, j'utilisé Google à mon avantage et trouvé cette question stackoverflow: What does this GCC error "... relocation truncated to fit..." mean? J'ai lu le matériel dans la première réponse, et parcouru google un peu plus, puis essayé la solution offerte dans la deuxième réponse. Voici mon script éditeur de liens

SECTIONS 
    { 
      . = 0x000000000000001b; 
      .text : 
      { 
        *(*) 
      } 
    } 

J'essaie de lier avec cette commande:

ld test.obj -T test.ld -lkernel32 --enable-stdcall-fixup /cygdrive/c/Windows/system32/kernel32.dll -o test.exe 

Et je reçois cette erreur: ld: cannot find -lkernel32

Je reçois cette erreur, peu importe où je place le -T test.ld option.

Je suis coincé et mon google-foo ne semble pas suffisant pour trouver de l'aide de cette façon. Je ne comprends pas pourquoi LD ne peut pas trouver kernel32 quand je spécifie un script d'éditeur de liens, et je ne sais pas non plus comment résoudre la troncature.

Si elle aide, le objdump avec les données de réinstallation pour test.obj est:

$ objdump -Sr test.obj 

    test.obj:  file format pe-x86-64 


    Disassembly of section .text: 

    0000000000000000 <_main>: 
     0: 55      push %rbp 
     1: 48 89 e5    mov %rsp,%rbp 
     4: 48 83 ec 04    sub $0x4,%rsp 
     8: 6a f5     pushq $0xfffffffffffffff5 
     a: e8 00 00 00 00   callq f <_main+0xf> 
          b: R_X86_64_PC32  [email protected] 
     f: 48 89 c3    mov %rax,%rbx 
     12: 6a 00     pushq $0x0 
     14: 48 8d 45 fc    lea -0x4(%rbp),%rax 
     18: 50      push %rax 
     19: 6a 0e     pushq $0xe 
     1b: 68 32 00 00 00   pushq $0x32 
          1c: R_X86_64_32 .text 
     20: 53      push %rbx 
     21: e8 00 00 00 00   callq 26 <_main+0x26> 
          22: R_X86_64_PC32  [email protected] 
     26: 48 89 ec    mov %rbp,%rsp 
     29: 5d      pop %rbp 
     2a: 6a 00     pushq $0x0 
     2c: e8 00 00 00 00   callq 31 <_main+0x31> 
          2d: R_X86_64_PC32  [email protected] 
     31: f4      hlt 

    0000000000000032 <message>: 
     32: 48      rex.W 
     33: 65 6c     gs insb (%dx),%es:(%rdi) 
     35: 6c      insb (%dx),%es:(%rdi) 
     36: 6f      outsl %ds:(%rsi),(%dx) 
     37: 2c 20     sub $0x20,%al 
     39: 57      push %rdi 
     3a: 6f      outsl %ds:(%rsi),(%dx) 
     3b: 72 6c     jb  a9 <message_end+0x69> 
     3d: 64 21 0a    and %ecx,%fs:(%rdx) 

Merci.

__SOLUTION EDIT__ pour les singes futurs Google:

En utilisant les informations contenues dans la réponse de @Jester, je réécrit le programme et il fonctionne maintenant comme prévu. Voici la source de travail:

   global main 
       extern [email protected] 
       extern [email protected] 
       extern [email protected] 

       section .text 
     main 
       push   rbp 
       mov    rbp, rsp 
       sub    rsp, 8 

       ; hStdOut = GetStdHandle(STD_OUTPUT_HANDLE) 
       ; ABI, pass in registers 
       mov    rcx, -11 
       call   [email protected] 
       mov    rbx, rax 

       ; WriteFile(hStdOut, message, length(message), &bytes, 0) 
       mov    rcx, rbx 
       lea    rax, [rel message] 
       mov    rdx, rax 
       mov    r8,  (message_end - message) 
       lea    rax, [rbp-8] 
       mov    r9,  rax 
       push   0 
       call   [email protected] 

       mov    rsp, rbp 
       pop    rbp 

       ; ExitProcess(0) 
       mov    rcx, 0 
       call   [email protected] 

       ; 
       hlt 

     message   db  'Hello, World!', 10 
     message_end 

Répondre

2

Le Windows 64-bit calling convention passe les quatre premiers paramètres de taille dans les registres entiers spécifiquement, RCX, RDX, R8 et R9. Seulement s'il y a plus de 4 arguments, ils sont passés sur la pile. Notez que ceci est contrairement à les conventions d'appel 32 bits courantes, qui transmettent tous les paramètres sur la pile.Cela dit, votre problème est le push message qui génère une relocalisation de 32 bits (puisque push ne prend que 32 bits immédiatement). Ce que vous devriez faire est de passer l'adresse de la chaîne, donc, pour résoudre ce problème, utilisez par exemple.

lea rax, [rel message] 
push rax 

Le mot-clé ici rel assure que l'adresse RIP relatif est utilisé, ce qui est d'usage pour les binaires 64 bits.

+0

D'accord, merci! Le binaire est maintenant lié, mais génère une erreur de segmentation sur l'appel WriteFile(). Est-ce dû à la convention d'appel sur x64 (est-ce ARM ABI?). Dans ce cas, devrais-je déplacer les arguments dans les registres r comme décrit sur cette page ?: http://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64/ –

+0

I vous avez lié la documentation officielle msdn ... et non, cela n'a rien à voir avec ARM. – Jester

+0

Okay. Je l'ai eu maintenant, et j'ai mis à jour l'op avec la source de travail. Merci beaucoup! –