汇编,x86:如何将标签推送到堆栈?

时间:2018-01-14 12:40:14

标签: assembly x86 att addressing-mode

给出数据:

.section data
data_set:
.long 2,5,33,54,2,76,4,37,43,223,98,70,255

如何将数据的起始地址(而不是该地址中的值)推送到堆栈?

我试过了:

pushl data_set

最终(在尝试访问此地址中的数据后)导致了段错误。

1 个答案:

答案 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