如果我的术语不正确,请原谅我。
我正在尝试实现一个基于 x86 gnu c 的系统,它能够将命令行参数传递给程序。不要与在程序中访问它们混淆,实际上是在将执行传递给用户程序之前设置堆栈。
从我收集到的内容中,argc 和 argv 被推入堆栈,但正是我遗漏了一些东西的构造过程。下面是我执行另一个程序的方式。
__asm__ __volatile__ ("pushl %%ds\n" /* save data and extra segment registers */
"pushl %%es\n"
"movl %%esp, %%ebx\n"
"movl %%ebx, oldsp\n"
"movl %%ss, %%ebx\n"
"movl %%ebx, oldss\n"
"movl %0, %%ds\n" /* set data segment to new user base */
"movl %0, %%ss\n"
"movl $0xfff0, %%ebx\n" /* start of the new user stack pointer */
"movl %%ebx, %%esp\n"
"movl %2, %%eax\n" /* place i into eax - push it onto the stack*/
"pushl %%eax\n"
"pushl %%eax\n"
"lcallw *%%fs:(%1)\n"
"movl %%fs:oldss, %%ebx\n"
"movl %%ebx, %%ss\n"
"movl %%fs:oldsp, %%ebx\n"
"movl %%ebx, %%esp\n"
"popl %%es\n" /* restore old segment registers */
"popl %%ds\n"
:
:"a" (userbase), "d" (&useg), "r" (i)
:"%ebx", "eax", "memory"); /* prevents gcc from optimizing useg away*/
我的印象是在堆栈指针更新后我可以将值压入堆栈。我显然没有得到我推入堆栈的值,所以我什至不确定我是否以正确的方式去做。
下面是一个简单的测试程序,它试图将 argc 打印到屏幕上。
.file "prog3.c"
#APP
.code16gcc
call main
lretw
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "\r\nstring: %u"
#NO_APP
.section .text.startup,"ax",@progbits
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
subl $16, %esp
movl 8(%ebp), %eax
movl %eax, 4(%esp)
movl $.LC0, (%esp)
call printf
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3"
.section .note.GNU-stack,"",@progbits
我已经查看了堆栈是如何为函数调用准备的,认为这可能是一个类似的过程,但我仍然处于断开状态。有什么想法吗?