2016-12-03 14 views
0

У меня есть файл NASM и файл C. Моя ОС Ubuntu 17.04 64 битСсылка C с NASM в 64 бит

Я следовал инструкциям из другого сообщения. Linking C with NASM

Вот мой код

main.c:

#include <stdio.h> 

int doit(int a, int b); 

int main() 
{ 
    printf("%d\n", doit(2,4)); 
    return 0; 
} 

doit.asm:

global doit 

section .data 

section .text 

doit: 

    xor rax, rax   ;sets rax to 0 

    mov eax, [rsp+8]  ;sets **b** to eax(32bit = int size) 
    add eax, [rsp+16]  ;adds **a** to eax(32bit = int size) 

    ret 

компилирования:

[email protected]:~/Desktop/TEST$ nasm -f elf64 doit.asm && gcc -Wall main.c doit.o 
[email protected]:~/Desktop/TEST$ ./a.out 318503633 
[email protected]:~/Desktop/TEST$ 

Как вы можете видеть, результат даже не близко к предсказанному результату, который является 6

Скажи, пожалуйста, почему результат отличается от 32-битного ассемблера

+0

Выпуск соглашение о вызове. 64-битный ABI System V можно найти [здесь] (https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-r252.pdf). Передача параметров описана в разделе 3.4.3_. Первые 6 параметров целочисленного класса передаются через регистры _RDI _, _ RSI _, _ RDX _, _ RCX _, _ R9_ и _R8_ в этом порядке. Целочисленные результаты класса возвращаются в _RAX_. На рис. 3.4 также показано, какие регистры должны быть сохранены функцией. Чтобы добавить 2 параметра, было бы так же просто, как «добавить rsi, rdi'' mov rax, rsi'' ret». Трюк для добавления 2 регистров и сохранения в третий будет «lea rax, [rdi + rsi]» –

ответ

0

Это довольно просто, вы используете различные соглашения о вызове По параметрам 64 передаются по регистрам Следовательно, ваш ассемблерный код ищет a, b параметры в стеке (с помощью esp) на 32 бит, которые вы передадите a, b над стеком Чтобы решить эту проблему, изучите соглашение о вызовах, используемое на x64, и узнайте, какие регистры используется для передачи параметров и определения того, что в вашем коде C Используйте objdump -d и изучите разборку этого кода, чтобы понять, что фактически открывается O r компилировать с помощью gcc -m32 и заставить компилятор использовать соглашение о собственном вызове (в стеке)

+0

32-разрядная система x86 V ABI не является «запатентованной». Я предполагаю, что это плохой автокоррект или что-то еще, поскольку отсутствие абзацев и пунктуации заставляет меня думать, что вы написали это на телефоне. –

+0

Да, я не могу на моем компьютере прямо сейчас, я с радостью исправлю это, когда это возможно. – DrPrItay

1

Вы не используете правильное соглашение о вызове. Linux на AMD64 использует System V AMD64 ABI.

main.c

#include <stdio.h> 

extern int sum (int a, int b); 

int main() 
{ 
    const int a = 2; 
    const int b = 3; 

    printf ("%d + %d = %d\n", a, b, sum (a, b)); 
    return 0; 
} 

sum.asm

 global sum 

     section .text 
sum: 
     mov eax, edi 
     add eax, esi 
     ret 

инструкции по сборке

nasm -f elf64 -o sum.o sum.asm 
gcc -o main.o -c main.c 
gcc -o main main.o sum.o 
+0

Соглашение о вызовах register-args позволяет более эффективный код: 'lea eax, [rdi + rsi]', который сохраняет MOV , (Обратите внимание на 32-разрядный операнд тоже. Прототип OP использует 'int' для аргументов и возвращаемого значения, поэтому нет смысла сохранять/работать с мусором в верхней половине 64-битного регистра, тем более, что он стоит в коде, размер для префикса REX.) (Хотя в автономной функции отступы перед следующей функцией на самом деле означают, что они берут 16B). –

+0

Кроме того, x86-64.org [мертв и, похоже, не возвращается] (http://stackoverflow.com/questions/18133812/where-is-the-x86-64-abi-документирован). : (См. [X86 tag wiki] (http://stackoverflow.com/tags/x86/info) для ссылок на документы ABI. Некоторым людям нравится связывать несколько недавних копий PDF на других сайтах. –

+0

Я изменил размеры операндов для соответствия C-подписи.Я сохранил явную инструкцию 'add' для ясности. –

 Смежные вопросы

  • Нет связанных вопросов^_^