PIC的大会

时间:2011-08-25 16:23:51

标签: assembly pic

str的地址存储在堆栈中(可以使用pop来获取它,并且它与位置无关):

.text
    str:
        .string "test\n"

但是现在str的地址不在堆栈中(不能使用pop来获取它,但是str(%rip)(RIP相对寻址)是PIC):

.text
    str:
        .skip 64

这是我在上一个问题中找到的,

但我不明白汇编程序如何决定str的地址是否应该在堆栈中?

我应该何时使用RIP相对寻址,还是使用pop使其成为PIC?

更新

这是有效的:

.text
    call start
    str:
        .string "test\n"
    start:
    movq    $1, %rax
    movq    $1, %rdi
    popq     %rsi
    movq    $5, %rdx
    syscall
    ret

但如果我将popq %rsi更改为lea str(%rip),%rsi,则会导致细分错误...

1 个答案:

答案 0 :(得分:1)

完全清楚:CALL指令将其后面的指令地址压入堆栈并跳转到目标地址。这意味着

x: call start 
y: 

在道德上等同于(忽略我们在此处废弃%rax):

x: lea y(%rip), %rax
   push %rax
   jmp start 
y: 

相反RET从堆栈中弹出一个地址并跳转到它。

现在,在您的代码中,您执行popq %rsi,然后ret跳回到您的任何内容。如果您只是popq更改为lea str(%rip), %rsi以加载地址为%rsi的{​​{1}},您仍然拥有返回值(地址{{ 1}})在堆栈上!要修复代码,只需手动弹出堆栈中的返回值(str)或者在函数后更加明智地移动str,这样您就不需要进行笨拙的调用。

更新了完整的独立示例:

add $8, %rsp

使用str反汇编代码可以发现代码确实与位置无关,即使使用# p.s # # Compile using: # gcc -c -fPIC -o p.o p.s # gcc -fPIC -nostdlib -o p -Wl,-estart p.o .text .global start # So we can use it as an entry point start: movq $1, %rax #sys_write movq $1, %rdi lea str(%rip), %rsi movq $5, %rdx syscall mov $60, %rax #sys_exit mov $0, %rdi syscall .data str: .string "test\n" 也是如此。

objdump -d p