我现在正在学习Gnu汇编,试图读字符串,但是是错误的。什么问题?
.text
.globl _start
MAX_CHAR=30
_start:
## Start message ##
movl $4, %eax
movl $1, %ebx
movl $msg, %ecx
movl $len, %edx
int $0x80
## READ ##
movl $3, %eax #sys_read (number 3)
movl $0, %ebx #stdin (number 0)
movl %esp, %ecx #starting point
movl $MAX_CHAR, %edx #max input
int $0x80 #call
## Need the cycle to count input length ##
movl $1, %ecx #counter
end_input:
xor %ebx, %ebx
mov (%esp), %ebx
add $1, %esp #get next char to compare
add $1, %ecx #counter+=1
cmp $0xa, %ebx #compare with "\n"
jne end_input #if not, continue
## WRITE ##
sub %ecx, %esp #start from the first input char
movl $4, %eax #sys_write (number 4)
movl $1, %ebx #stdout (number 1)
movl %ecx, %edx #start pointer
movl %esp, %ecx #length
int $0x80 #call
## EXIT ##
movl $1, %eax
int $0x80
.data
msg: .ascii "Insert an input:\n"
len =.-msg
1条答案
按热度按时间of1yzvn41#
我看到的错误:
%esp
中当前地址的下面;例如,信号处理程序可能会在任何时候意外地覆盖它,所以你需要从%esp
中减去,为缓冲区分配空间,然后在完成时再加回来。%esp
应该始终保持4字节对齐。这不是严格的体系结构要求,但违反此规则将导致执行效率低下和大量混乱。因此,要为30字节缓冲区创建空间,请将%esp
向上舍入并减去32。当你想调用用C语言编写的函数时,还有额外的对齐要求,请参见gcc x86-32 stack alignment and calling printf。
%esp
作为指针变量:不要管它,选择其他寄存器。l
后缀和/或32位寄存器的使用(eax、ebx等)发出32位指令信号。因此mov (%esp), %ebx
从内存中加载4个字节,和cmp $0xa, %ebx
将它们与32位值0x0000000a
进行比较。因此,除非内存中的下三个字节恰好都是零,否则比较将是错误的。要进行8位操作,请使用8位寄存器(a1、b1、ah、bh等),但要注意它们与相应的16位和32位寄存器重叠;因此不要尝试同时使用%ebx
和%bl
来处理不同的事情。(如上所述,%reg
不应是%esp
,而是您使用的任何寄存器)和cmpb $0xa, %bl
。b
后缀是可选的,因为其大小是从8位bl
寄存器推断出来的,但由于您在其余的cod中使用了后缀,因此最好保持一致。)-m32
标志。从长远来看,您可能更愿意学习64位x86汇编; 32位x86代码已经过时了。read
的返回值。在read系统调用返回后,它留在%eax
中。(如果它为零,则到达文件结尾;如果是负数,则表示有错误。)此外,如果在默认模式下从终端阅读,通常一次最多只能读取一行,因此如果存在
\n
,它将对应于read
返回的输入的结尾(但如果标准输入是从文件重定向的,则这不适用)。