我正在尝试学习一些非常基本的ASM,以帮助我阅读gdb输出找出东西。我一直在线学习一些教程,并且遇到了一些我无法弄清楚如何做的事情。
我正在关注的教程(http://programminggroundup.blogspot.fr/2007/01/programming-from-ground-up.html)讨论了第5章中的字符串IO。它使用.bss段为输入声明一个500长度的数组。我可以让这个工作没问题。但是,我现在正在尝试将数组放在堆栈上,而不是放在.bss段(对我来说看起来像'全局内存')。
问题是,我无法弄清楚我做错了什么。据我所知,我在堆栈上移动了一个64字节的部分,我试图用它来保存输入,然后输出它。代码没有核心或以其他方式表示,但是当我运行它并输入“Hello”(没有引号)时,结果是“ello”,写在下一个命令行中。接下来是行返回,因此“ello”会在程序终止时立即执行。
user_omitted@serveromitted:~/folderomitted>./basic_io
Hello
user_omitted@serveromitted:~/folderomitted>ello
据我所知,我正在写入堆栈。我希望我不需要将其归零,因为输入应该正确覆盖内容。我在做一些疯狂的错误吗?
这是使用带有气体的unix IA-64系统。另外,如果我做的事情真的很愚蠢(不仅仅与我的问题有关),请告诉我!
.section .text
.globl _start
_start:
pushq %rbp # Store the original base pointer on the stack
mov %rsp, %rbp # The new base pointer is targeting the start of the stack
sub $64, %rsp # Move the stack pointer down by 64 bytes, thus saying we have 64 bytes to play with
mov %rsp, %rcx # Pass the content of the stack pointer to rcx, for the system call
mov $64, %rdx # Store the length of the buffer
mov $3, %rax # State that we want to use system_read
mov $0, %rbx # Select the handler (STDIN)
int $0x80 # invoke
mov $4, %rax # system_write
mov $1, %rbx # STDOUT
mov $64, %rdx # length of buffer
mov %rsp, %rcx # location of the buffer on the stack
int $0x80 # invoke
mov %rbp, %rsp # Restore the stack pointer to the original location
popq %rbp # pop the base pointer off the stack
mov $1, %rax # sys_exit
mov $0, %rbx # return code
int $0x80 # invoke
答案 0 :(得分:1)
这看起来像是同一个问题:
Linux write sys call using string on stack
免责声明:我正在运行32位硬件,没有使用64位代码的经验。对于64位代码,使用32位引用(Jon Bartlett的优秀PGU!)“可能”是错误的。如上面的链接(和右侧)所示,您使用的是32位系统调用号,将参数放在适合32位代码的寄存器中,并使用32位int 0x80
。我被告知这是有效的(仍然),你确认它适用于.bss
中的缓冲区。我认为%rsp
“太高”,如链接所示。
在任何情况下,sys_read
都不会返回以零结尾的字符串,sys_write
如果有,则不会注意它。 sys_write
写入%edx
(%rdx
)中的字节数,无论它是否为“垃圾”。 sys_read
返回%eax
(%rax
)中实际输入的字节数,这是您要放入%edx
(%rdx
)的内容(同一个寄存器)对于sys_write
,对于这种情况下的32位或64位代码)。这不是你的问题,但它仍然是“错误的”。
如果讨厌的用户在32位代码中输入的%edx
允许的次数超过允许的话,我会在命令提示符下看到“过剩”这个问题。这可能是“危险的”!如有必要,“冲洗缓冲区”可能是个好主意。如果%eax
(%rax
)小于%edx
(%rdx
),那么您没问题。如果它们相等,请检查缓冲区中的最后一个字节是否有换行符(ascii代码0xa)。如果它在那里,你没事。如果没有,请继续阅读,直至找到换行符。对于您是唯一用户的玩具程序来说,这可能是“过度杀伤”,但了解这个问题仍然是一个好主意。