在x86 AT & T synatax中,如何將ASCII字符串推入堆棧? (或者C程序如何將ASCII字符串推入堆棧?)如何在x86中將字符串推入堆棧(AT&T語法)
我的初始嘗試是創建數據段,使用.asciz,然後使用LEA和MOV使用位移來推送事物。但這一切都以錯誤結束。
在x86 AT & T synatax中,如何將ASCII字符串推入堆棧? (或者C程序如何將ASCII字符串推入堆棧?)如何在x86中將字符串推入堆棧(AT&T語法)
我的初始嘗試是創建數據段,使用.asciz,然後使用LEA和MOV使用位移來推送事物。但這一切都以錯誤結束。
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在寄存器中。)
這是從我寫的教程中,您只需要定義您的字符串,然後將字符串移動到堆棧。實際上它只是移動起始地址,然後當你想要打印時,你可以指定偏移量的長度。
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
這不是AT&T語法 –
等等,你的意思是堆棧('%rsp')還是其他堆棧? (即堆棧數據結構) –