给出数据:
.section data
data_set:
.long 2,5,33,54,2,76,4,37,43,223,98,70,255
如何将数据的起始地址(而不是该地址中的值)推送到堆栈?
我试过了:
pushl data_set
最终(在尝试访问此地址中的数据后)导致了段错误。
答案 0 :(得分:4)
在AT& T语法中,要使用地址作为指令的直接操作数,请使用$label
。
您需要pushl $data_set
指示push imm32
。,就像您push $123
一样。
pushl data_set
会推送从地址data_set
加载的数据,即
push m32
。
从概念上讲,AT& T语法将所有内容视为潜在地址。因此label
是一个地址,0x123
也是。{1}}。因此add 0x123, %eax
从地址0x123
加载,add label, %eax
从地址label
加载。如果希望将数字作为直接操作数,则使用add $0x123, %eax
。使用符号地址作为立即操作数的工作方式相同。
无论哪种方式,地址都被编码到指令中,这只是一个问题,它是在寻址模式中是立即还是位移。这就是你使用
的原因
add $(foo - bar), %eax
添加两个符号之间的距离,而不是
add $foo-$bar, %eax
(寻找名为$bar
的符号,即$
是符号名称的一部分)。 $
适用于整个操作数,而不适用于符号/标签名称。相关:more about assemble-time math in GAS
在其他情况下,例如作为.long
或.quad
的操作数,没有立即与内存操作数问题,因此您只需编写dataptr: .long data_set
来发出保存data_set
地址的4字节数据,就像你从C static int *dataptr = data_set;
获得
您可以通过查看
的C编译器输出来检查语法void ext(int*);
static int data[] = {1,2,3};
void foo() {
ext(data);
}
让C编译器发出将符号地址传递给函数的代码。我把它放在the Godbolt compiler explorer上,确实使用了pushl $data
。