【发布时间】:2013-08-26 16:06:48
【问题描述】:
通读《专业汇编语言书》;它似乎为读取命令行参数提供了错误的代码。我稍微纠正了一下,现在它从段错误变为读取参数计数,然后是段错误。
这是完整的代码:
.data
output1:
.asciz "There are %d params:\n"
output2:
.asciz "%s\n"
.text
.globl main
main:
movl 4(%esp), %ecx /* Get argument count. */
pushl %ecx
pushl $output1
call printf
addl $4, %esp /* remove output1 */
/* ECX was corrupted by the printf call,
pop it off the stack so that we get it's original
value. */
popl %ecx
/* We don't want to corrupt the stack pointer
as we move ebp to point to the next command-line
argument. */
movl %esp, %ebp
/* Remove argument count from EBP. */
addl $4, %ebp
pr_arg:
pushl (%ebp)
pushl $output2
call printf
addl $8, %esp /* remove output2 and current argument. */
addl $4, %ebp /* Jump to next argument. */
loop pr_arg
/* Done. */
pushl $0
call exit
书中的代码:
.section .data
output1:
.asciz “There are %d parameters:\n”
output2:
.asciz “%s\n”
.section .text
.globl _start
_start:
movl (%esp), %ecx
pushl %ecx
pushl $output1
call printf
addl $4, %esp
popl %ecx
movl %esp, %ebp
addl $4, %ebp
loop1:
pushl %ecx
pushl (%ebp)
pushl $output2
call printf
addl $8, %esp
popl %ecx
addl $4, %ebp
loop loop1
pushl $0
call exit
用 GCC (gcc cmd.S) 编译它,也许这就是问题所在? __libc_start_main 以某种方式修改堆栈?不太确定...
更糟糕的是,尝试调试它以查看堆栈,但 GDB 似乎抛出了很多与 printf 相关的东西(其中之一是 printf.c: File not found 或类似的东西)。
【问题讨论】:
-
movl %esp, %ebp/addl $4, %ebp你不是把ebp指向argc吗?在我看来,如果你想要argv,你应该加 8。 -
好吧,
4(%esp)和4(%ebp)指向 argc,所以我要删除 argc,因此(%ebp)应该指向 argv[0] 对吗? -
在我看来,当您到达
/* Remove argument count from EBP. */点时,您的esp将指向与您输入main时相同的位置,因此esp+4指向argc。因此,要使ebp指向argv,我猜你应该添加 8 而不是 4。 -
你是对的。我按照你说的做了,但是输出如下:codepad.org/h2VnzD2J
-
我可能记错了,但您在访问
argv时似乎遗漏了一级间接性。您的代码似乎假定esp+8是argv[0],esp+12是argv[1]等。据我回忆,它应该类似于mov eax,[esp+8] ; get argv/mov ebx,[eax] ; get argv[0]/mov ecx,[eax+4] ; get argv[1]等。
标签: linux assembly x86 gnu-assembler