[英]how to push a string into a stack in x86 (AT&T syntax)
在 x86 AT&T 语法中,如何将 ASCII 字符串压入堆栈? (或者 C 程序如何将 ASCII 字符串压入堆栈?)
我最初的尝试是创建数据部分,使用 .asciz,然后使用 LEA 和 MOV 使用位移推送东西。 但这一切都以错误告终。
C 程序不推送字符串,它们推送指向字符串的指针。
Asm 程序可以将可变长度的东西压入堆栈,但它很奇怪而且很少有用。 在优化你的代码时,只有在考虑正常方式后才考虑它。
它对于为一次只能使用一个字节的可变大小输入分配空间当然很有用,例如读取输入。 (就像一个局部可变大小的数组,除了你在读取输入时增长它,而不是在你完成读取之前选择一个大小。)
无论如何,正常的方式(推送一个指针)是这样的:
static const char str[] = "Hello World!";
void foo(const char*p);
int hello(void) {
foo(str);
return 0;
}
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 的 args。 使用static const char *str
可以让编译器在编译时解析间接push $.LC0, %edi
并push $.LC0, %edi
,而.LC0
在 .rodata 部分放置指向.LC0
的指针。
在 64 位模式下,使用-fPIC
进行编译将强制编译器使用 RIP 相关的lea
而不是 mov-immediate。 在 32 位代码-fPIC
,生成一些非常笨重的东西来获取 EIP 的当前值并在全局偏移表中找到符号地址。
我让hello
返回 0 而不是 void,所以我不必解释尾调用优化( jmp
而不是call
)。 (这在 32 位模式下不会发生,因为调用者必须在 foo 返回后弹出 arg。当我第一次写这个答案时,我忘记了问题是关于堆栈的,而不仅仅是将字符串传递给函数。64 位 ABI 通过寄存器中的参数。)
这是我写的一个教程,你只需要定义你的字符串,然后将字符串移动到堆栈中。 实际上,它只移动起始地址,然后当您要打印时指定偏移量的长度。
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.