2016-01-28 81 views
1

在x86 AT & T synatax中,如何將ASCII字符串推入堆棧? (或者C程序如何將ASCII字符串推入堆棧?)如何在x86中將字符串推入堆棧(AT&T語法)

我的初始嘗試是創建數據段,使用.asciz,然後使用LEA和MOV使用位移來推送事物。但這一切都以錯誤結束。

+0

等等,你的意思是堆棧('%rsp')還是其他堆棧? (即堆棧數據結構) –

回答

0

C程序不會推送字符串,它們會將指針指向字符串。

Asm程序可以將可變長度的東西推送到堆棧上,但它很奇怪,很少有用。在優化你的代碼時,只考慮考慮正常的方式。

對於一次只能使用一個字節的可變大小輸入(例如讀取輸入)分配空間肯定會很有用。 (就像本地可變大小的數組一樣,除了在讀取輸入時增大它的大小,而不必在完成讀取之前選擇大小。)

無論如何,正常方法(按指針)看起來像這樣:

static const char str[] = "Hello World!"; 
void foo(const char*p); 
int hello(void) { 
    foo(str); 
    return 0; 
} 

and compiles to the following 32bit code (where the calling convention uses the stack)

hello: 
     subl $24, %esp  # keep the stack aligned for foo() 
     pushl $str   # push-immediate with the address of the string 
     call foo 
     xorl %eax, %eax  # return value 
     addl $28, %esp  # pop the arg and the padding 
     ret 

.section  .rodata 
     .align 8 
str: 
     .string "Hello World!" 

請注意,我用const char str[]代替const char *str所以符號地址將是字符串常量的地址,而不是一個指針的地址。使用const char *str會導致加載(推送內存的內容)而不是立即執行,以設置foo的參數。使用static const char *str可讓編譯器在編譯時解析間接尋址,並且push $.LC0, %edi,絕對不會在「.rodata」部分中指向.LC0

在64位模式下,使用-fPIC進行編譯將強制編譯器使用RIP相關的lea而不是mov-immediate。在32位代碼-fPIC中,生成一些非常笨重的東西來獲取EIP的當前值,並在Global Offset Table中找到符號地址。

我發的hello返回0而不是也是無效的,所以我不必解釋尾部優化(jmp而不是call)。 (這在32位模式下不會發生,因爲調用者必須在foo返回後彈出arg,當我第一次寫這個答案時,我忘了問題是關於堆棧,而不是僅僅將字符串傳遞給函數。 args在寄存器中。)

-1

這是從我寫的教程中,您只需要定義您的字符串,然後將字符串移動到堆棧。實際上它只是移動起始地址,然後當你想要打印時,你可以指定偏移量的長度。

Compiling assembler: nasm -felf64 "helloworld.asm"... 
Linking object helloworld.o: ld -melf_x86_64 -o helloworld helloworld.o ... 
Displaying helloworld.asm asm source: 
section  .text 
global  _start        ;must be declared for linker (ld) 

_start:           ;tell linker entry point 

    mov  rdx,len        ;message length 
    mov  rcx,msg        ;message to write 
    mov  rbx,1        ;file descriptor (stdout) 
    mov  rax,4        ;system call number (sys_write) 
    int  0x80        ;call kernel 

    mov  rax,1        ;system call number (sys_exit) 
    int  0x80        ;call kernel 

section  .data 

msg  db 'Hello, world!',0xa     ;our dear string 
len  equ $ - msg        ;length of our dear string 

Executing linked helloworld executable! ./helloworld | figlet .. 
_ _  _ _        _  _ _ 
| | | | ___| | | ___ __  _____ _ __| | __| | | 
| |_| |/ _ \ | |/ _ \ \ \ /\// _ \| '__| |/ _` | | 
| _ | __/ | | (_) | \ V V/(_) | | | | (_| |_| 
|_| |_|\___|_|_|\___() \_/\_/ \___/|_| |_|\__,_(_) 
        |/         
./helloworld: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped 
+0

這不是AT&T語法 –