【发布时间】:2018-02-05 21:30:36
【问题描述】:
我正在尝试在汇编程序中设置一些指针(在 x86_64 linux 上运行的 AT&T 语法),然后将它们传递给 C 程序以实质上添加它们的值。当然,这不是实现最终结果的最有效方式,但我正在尝试了解如何使这样的事情发挥作用,以便进一步构建它。 C 程序如下所示:
#include <stdio.h>
extern void iplus(long *a, long *b, long *c){
printf("Starting\n");
long r= *a + *b;
printf("R setup\n");
*c=r;
printf("Done\n");
}
这需要三个长指针,将前两个的值相加,然后将该值存储在第三个中。如上所示,它会在每个点打印一条有关其状态的消息,以跟踪发生分段错误的位置。
引用该函数的汇编程序如下:
.extern exit
.extern malloc
.data
vars: .zero 24 /*stores pointer addresses*/
.text
FORI: .ascii "%d\0" /*format for printing integer*/
.global main
main:
and $~0xf, %rsp /*16-byte align the stack*/
movq $8,%rdi
call malloc
movq %rax,(vars+0) /*allocate 8 bytes and put its address into the variable*/
movq $8,%rdi
call malloc
movq %rax,(vars+8)
movq $8,%rdi
call malloc
movq %rax,(vars+16)
movq $3,((vars+0)) /*first addend 3*/
movq $7,((vars+8)) /*second addend 7*/
movq $0,((vars+16))
movq (vars),%rdi
movq (vars+8),%rsi
movq (vars+16),%rdx
call iplus /*call the function with these values*/
movq $FORI,%rdi
movq ((vars+16)),%rsi
call printf /*print the sum, "10" expected*/
call exit
在执行上述程序后,我得到以下输出:
Starting
Segmentation fault (core dumped)
意味着该函数似乎已成功调用,但该函数中的第一个操作long r = *a + *b; 或更早的一些仅在此时成为问题的东西导致了段错误。我期望发生的是,对于 24 字节 vars 保存的三个 8 字节值,malloc 返回的地址(每次分配 8 个字节)被存储。然后,该地址指向一个 8 字节整数,分别设置为 3、7 和 0。这些整数的地址(即 vars 中保存的值)被传递给 iplus 以便对它们求和,然后使用printf 打印总和。由于我无法确定的原因,这反而会导致段错误。
为什么会出现段错误?是否可以使用 C 函数调用来执行这种加法,并且基本上仍然使用双指针的结构?
【问题讨论】:
-
您没有传递地址。您缺少
$标志,例如movq (vars),%rdi应该是movq $vars,%rdi等等。leaq vars, %rdi也可以。 -
您可能已经知道了,但我仍然存在误解,但请确保您看到了其中数据的布局方式。
vars指的是包含 3 个连续的 8 字节 地址 的数据,这些地址指向由malloc分配的内存,这是存储整数的地方。例如(vars+8)是加数之一的地址,而不是加数本身的值。 -
哦,所以你希望这个
movq $3,((vars+0))是双重间接的?不是,x86 中没有这样的东西。那么你需要做movq vars, %rax; movq $3, (%rax)等等。
标签: c assembly segmentation-fault x86-64 function-calls