Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unix 使用asm的基于堆栈的字符串IO-我做错了什么?_Unix_Assembly_Gnu Assembler - Fatal编程技术网

Unix 使用asm的基于堆栈的字符串IO-我做错了什么?

Unix 使用asm的基于堆栈的字符串IO-我做错了什么?,unix,assembly,gnu-assembler,Unix,Assembly,Gnu Assembler,我正在尝试学习一些非常基本的ASM,以便帮助我阅读gdb输出,了解一些东西。我一直在网上学习一些教程,遇到了一些我不知道该怎么做的事情 我下面的教程()在第5章讨论了字符串IO。它使用.bss段为输入声明一个500长度的数组。我可以让它工作没有问题。但是,我现在尝试将数组放在堆栈上,而不是放在.bss段中(在我看来,它就像“全局内存”) 问题是,我不知道我做错了什么。在这里我可以看到,我在堆栈上移动了一个64字节的部分,我试图用它来保存输入,然后输出它。代码不进行核心处理或其他expode,但当

我正在尝试学习一些非常基本的ASM,以便帮助我阅读gdb输出,了解一些东西。我一直在网上学习一些教程,遇到了一些我不知道该怎么做的事情

我下面的教程()在第5章讨论了字符串IO。它使用.bss段为输入声明一个500长度的数组。我可以让它工作没有问题。但是,我现在尝试将数组放在堆栈上,而不是放在.bss段中(在我看来,它就像“全局内存”)

问题是,我不知道我做错了什么。在这里我可以看到,我在堆栈上移动了一个64字节的部分,我试图用它来保存输入,然后输出它。代码不进行核心处理或其他expode,但当我运行它并键入“Hello”(不带引号)时,结果是“ello”,写在下一个命令行中。然后返回行,因此在程序终止时立即执行“ello”

user_omitted@serveromitted:~/folderomitted>./basic_io
Hello
user_omitted@serveromitted:~/folderomitted>ello
据我所见,我正在向堆栈中写入。我希望我不需要将其归零,因为输入应该正确覆盖内容。我是不是做错什么了

这是使用带gas的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

这看起来是同一个问题:

免责声明:我正在运行32位硬件,没有使用64位代码的经验。对64位代码使用32位引用(Jon Bartlett的优秀PGU!)“可能”是一个错误。如上面(和右边)的链接所示,您使用的是32位系统调用号,将参数放入适合32位代码的寄存器中,并使用32位
int 0x80
。我被告知这是有效的(仍然有效),您确认它与
.bss
中的缓冲区一起工作。如链接所示,我认为
%rsp
太高了

在任何情况下,
sys\u read
都不会返回以零结尾的字符串,
sys\u write
如果返回,就不会注意它
sys_write
写入
%edx
%rdx
)中的字节数,无论它是否为“垃圾”
sys\u read
返回在
%eax
%rax
)中实际输入的字节数,这就是您要为
%edx
%rdx
)(在这种情况下,32位或64位代码的寄存器)写入
的字节数。这不是你的问题,但它仍然是“错误的”


我已经看到,如果讨厌的用户在32位代码中键入的内容超出了
%edx
中允许的范围,那么命令提示中将出现“过量”问题。这是潜在的“危险”!如果有必要,“刷新缓冲区”可能是个好主意。如果
%eax
%rax
)小于
%edx
%rdx
),您就没事了。如果它们相等,请检查换行缓冲区中的最后一个字节(ascii代码0xa)。如果它在那里,你就没事了。如果没有,请继续阅读,直到找到换行符。对于您是唯一用户的玩具程序来说,这可能是“杀伤力过大”,但注意这个问题仍然是一个好主意。

由于这是64位代码,您可能希望从使用传统系统调用(
int 0x80
)切换到使用
syscall
指令。请注意,用于参数的寄存器会有所不同(请参阅),syscall枚举数也会有所不同(请参阅)。谢谢-我将其转换为x86,并以32位模式进行组装/链接,它工作得非常好。现在我将坚持使用32位,而我会按照教程进行操作,然后再跳到64位。