【问题标题】:Link C with NASM in 64 bit用 64 位的 NASM 链接 C
【发布时间】:2016-12-03 10:54:05
【问题描述】:

我有一个 NASM 文件和一个 C 文件。我的操作系统是 Ubuntu 17.04 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

编译:

 home@main:~/Desktop/TEST$ nasm -f elf64 doit.asm && gcc -Wall main.c doit.o
 home@main:~/Desktop/TEST$ ./a.out 318503633
 home@main:~/Desktop/TEST$

如您所见,结果甚至与预测结果相差无几,即 6

请告诉我为什么结果与 32 位 asm 不同

【问题讨论】:

  • 问题是调用约定。 System V 64 位 ABI 可以是 found here第 3.4.3 节 中介绍了参数传递。前 6 个整数类参数通过寄存器 RDIRSIRDXRCX 传入R9R8 的顺序。 RAX 中返回整数类结果。图 3.4 还显示了哪些寄存器需要由函数保存。添加 2 个参数就像 add rsi, rdi mov rax, rsi ret 一样简单。添加 2 个寄存器并保存到第三个的技巧是 lea rax, [rdi+rsi]

标签: c assembly parameters nasm x86-64


【解决方案1】:

这很简单,您使用不同的调用约定 在 x64 上,参数由寄存器传递 因此,您的汇编代码正在寻找 32 位堆栈上的 a、b 参数(使用 esp),您将通过堆栈传递 a、b 为了解决这个问题,要么研究 x64 上使用的调用约定,并了解哪些寄存器用于传递参数以及如何在 C 代码中确定它 使用 objdump -d 并研究该代码的反汇编以了解实际打开的内容 或者使用gcc -m32 编译并强制编译器使用专有调用约定(在堆栈上)

【讨论】:

  • 32 位 x86 System V ABI 不是“专有的”。我认为这是不好的自动更正之类的东西,因为缺少段落和标点符号让我觉得你是在手机上写的。
  • 是的,我的电脑现在不可用,如果可能,我会很乐意解决这个问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-30
  • 1970-01-01
  • 2014-09-19
  • 2012-02-10
  • 2011-11-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多