【问题标题】:C passes value instead of address to assembly function (x64)C将值而不是地址传递给汇编函数(x64)
【发布时间】:2015-04-29 08:10:51
【问题描述】:

我需要将我的字段的地址而不是值从 C 传递给汇编函数,我不知道为什么我最终得到的是值而不是地址。

C 代码:

long n = 1,ret = 0;
fun(&n, &ret);
//the rest is omitted

汇编代码:

.globl fun
fun:

pushq %rbp
movq %rsp, %rbp

movq 16(%rbp), %rax #my n address
movq 24(%rbp), %rbx #my ret address

cmpq $0, %rax
//the rest is omitted

当我使用 gdb 查看 %rax 和 %rbx 的值时,我可以看到我的寄存器中有值:

Breakpoint 1, fun () at cw.s:6
6       movq 16(%rbp), %rax #my n address
(gdb) s
7       movq 24(%rbp), %rbx #my ret address
(gdb) s
9       cmpq $0, %rax
(gdb) p $rax
$1 = 1
(gdb) p $rbx
$2 = 0

我真的看不出我的代码有什么问题。我确信 &n 使 C 传递地址而不是值。我正在遵循此处提供的解决方案,但没有运气。

Calling a C function in assembly

更新:

我在 AMD x86_64 上运行 LXLE(它是 Ubuntu 的一个分支)。使用的编译器是 gcc (Ubuntu 4.8.2-19ubuntu1) 和 GNU assembler (GNU Binutils for Ubuntu) 2.24。我的makefile:

cw: cw.c cw.o
    gcc cw.o cw.c -o cw
cw.o: cw.s
    as -gstabs -o cw.o cw.s

【问题讨论】:

  • 你的函数定义是什么?这只是电话。如果您的定义包含 int,则可能存在指向 int 转换的隐式指针。
  • 我会在 C 代码中放置一个断点,然后查看编译器生成的程序集。我的猜测是您在代码中添加了&s 作为事后的想法,并且不知何故忘记了重新编译 C 代码。
  • 尝试info registers 而不是p $rax..
  • 如果我没有任何关于 C 函数 fun 的声明/定义怎么办?

标签: c pointers assembly


【解决方案1】:

你在什么架构上?哪个编译器生成了fun 的代码?你自己写的吗?

代码使用的是 r* 寄存器,而您的问题提到了“x64”,所以我认为它是一些 amd64/x86-64/x64 架构。您正在从堆栈中读取内容(您已将其评论为“我的 n/ret 地址”),我认为您希望函数参数在那里,但我不知道该 CPU 系列上的任何 ABI将第一个参数传递给堆栈上的函数。

如果您自己编写,则需要阅读您的操作系统/编译器使用的 ABI 的调用约定,因为除非您使用的是非常晦涩的操作系统,否则它不会传递(前几个)函数参数在堆栈上。很可能您只是从堆栈中读取随机值,这些值恰好与编译器将值放入调用函数的位置相匹配。

如果您使用的是 Linux 或大多数其他使用 SysV ABI 的类 unix 系统,则函数的前两个参数将位于 rdi、rsi 寄存器中。如果你在 Windows 上,那将是 rcx,rdx。这是假设您的参数是 int/long/pointers。如果参数是结构、浮点等,则适用其他规则。

【讨论】:

猜你喜欢
  • 2020-01-09
  • 1970-01-01
  • 1970-01-01
  • 2011-07-08
  • 2014-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-07
相关资源
最近更新 更多