2011-08-25 31 views
2

str的地址存儲在堆棧(可使用pop取水的時候,它的位置無關):大會PIC

.text 
    str: 
     .string "test\n" 

但現在的str地址不在堆棧(不能使用pop去取,但str(%rip)(RIP相對尋址)是PIC):

.text 
    str: 
     .skip 64 

這是我從我剛纔的問題中發現,

但我不明白彙編程序如何決定地址str應該在堆棧中還是不在?

我應該使用RIP相對尋址,還是使用pop來使它成爲PIC?

UPDATE

這是工作:

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

但是,如果我改變popq %rsilea str(%rip),%rsi,它wlll導致段錯誤...

+1

彙編程序不能將任何東西放在堆棧上,因爲直到運行時纔會創建堆棧。除非你把它放在那裏,否則什麼都不在。 – ughoavgfhw

+0

@Je Rog:在這兩種情況下,'str'都與函數的代碼一起位於文本段中 - pop將不會檢索任何內容。你在問絕對和相對尋址模式之間的區別,因爲[wikipedia](http://en.wikipedia.org/wiki/Addressing_mode)有一個體面的討論嗎? – user786653

+0

@ user786653,爲什麼這個工作如果地址沒有存儲在堆棧上?注意'popq%rsi'。 http://pastebin.com/tZ81FvZK –

回答

1

只是要徹底清楚:CALL指令將其後的指令地址推入堆棧並跳轉到目標地址。這意味着,

x: call start 
y: 

在道德上是等同於(忽略我們垃圾%rax這裏):

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

相反RET從棧中彈出一個地址並跳轉到它。

現在在你的代碼中你做了popq %rsi然後ret跳回到你稱呼的任何東西。如果你只是更改popqlea str(%rip), %rsi加載%rsi與地址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代碼顯示,代碼確實位置無關,使用.data時也是如此。

p:  file format elf64-x86-64 
Disassembly of section .text: 
000000000040010c <start>: 
    40010c: 48 c7 c0 01 00 00 00 mov $0x1,%rax 
    400113: 48 c7 c7 01 00 00 00 mov $0x1,%rdi 
    40011a: 48 8d 35 1b 00 20 00 lea 0x20001b(%rip),%rsi  # 60013c <str> 
    400121: 48 c7 c2 05 00 00 00 mov $0x5,%rdx 
    400128: 0f 05     syscall 
    40012a: 48 c7 c0 3c 00 00 00 mov $0x3c,%rax 
    400131: 48 c7 c7 00 00 00 00 mov $0x0,%rdi 
    400138: 0f 05     syscall 
+0

它真的與'.data xxx'彙編不會是PIC?當以'gcc -nostdlib file.s -ggdb -o x; ./ x'運行時,它仍然導致段錯誤,當沒有stdlib的時候,x的調用者是什麼? –

+0

@Je Rog:不,你只需要記住使用RIP相對尋址(在命令行上可能是'-fPIC',取決於你想要實現的目標)。是的,如果你只是像這樣運行它(但你的問題也會如此),代碼將會出現段錯誤,我假定你仍然在使用上一個問題中的加載器。如果你希望它獨立工作,你需要使用sys_exit(60)來結束程序,沒有什麼可返回的。 ('mov $ 60,%rax''mov $ 0,%rdi'' syscall')。 – user786653

+0

我只是在'str'之前加了'.data',即使我用'-fPIC'編譯也不行...... –