2

我想了解 GNU 的以下行为。

OS X 上的以下测试程序(Apple cctools-822/GNU as 1.38)

    .globl foo
    jmp foo
foo:
    ret

被编码为

    00000000    e900000000    jmp         0x00000005
foo:
    00000005    c3            ret

而 GNU as on Linux (GNU as 2.22) 编码为

                                .global foo
    0000        E9FCFFFF        jmp 0x35 # foo
                FF
foo:
    0005        C3              ret

为什么后者会(对我)奇怪的跳跃?

此外,显然这个魔术0xfcffffff地址用于每次跳转到全局标签:

测试2.s

    .globl foo
    jmp foo
    .globl bar
    jmp bar
    .globl baz
    jmp baz
foo:
    push $1
    ret
bar:
    push $2
    ret
baz:
    push $3
    ret

在 linux 上使用 GNU 生成(GNU 为 2.22)

                        .globl foo
    0000    E9FCFFFF    jmp foo
            FF
                        .globl bar
    0005    E9FCFFFF    jmp bar
            FF
                        .globl baz
    000a    E9FCFFFF    jmp baz
            FF
foo:
    000f    6A01        push $1
    0011    C3          ret
bar:
    0012    6A02        push $2
    0014    C3          ret
baz:
    0015    6A03        push $3
    0017    C3          ret

谁能解释这种行为?

4

2 回答 2

2

它只是一种不同类型的重定位条目 (R_386_PC32)。

您不必担心,链接器会插入正确的地址。

如果您添加-r选项,您可以看到重定位条目objdump,例如

objdump -Dr test2.o

请注意,该值是0xfffffffc = -4因为 x86 是小端。

另请参阅此问题

于 2012-06-11T12:54:00.030 回答
1

我假设您正在反汇编对象而不是可执行文件?这对于所有工具链,所有在喜欢之前编译为对象的语言都是非常典型的。链接器...链接...对象,将全局变量,函数名称,变量等链接在一起。在链接阶段之前,您无法知道您所在的地址空间以及变量名称,因此某些本地人取决于在链接时间之前无法解析指令集和到达长度以及全局变量,因此该对象将放置某种填充数据,而不是可能会以一种奇怪的方式反汇编的指令。

于 2012-06-11T14:18:11.960 回答