我用程序集制作了简单的参数加法器,但它不起作用
它总是返回 0
.section .data
.section .text
.global _start
_start:
call adder
movl %eax,%ebx
movl $1,%eax
int $0x80
adder:
pushl %ebp
movl %esp,%ebp
movl $0,%eax #eax = return
movl $1,%ebx #ebx = index
movl 8(%ebp),%ecx #number of args
loop:
cmpl %ebx,%ecx
jg exit
addl 8(%ebp,%ebx,4),%eax
incl %ebx
jmp loop
exit:
movl %ebp,%esp
popl %ebp
ret
最佳答案
此代码存在一些问题,但您的方向是正确的。
1。循环条件
当 ebx >= ecx
时,您正在使用它来退出循环:
cmpl %ebx,%ecx
jg exit
语法相当困惑,但这实际上意味着“如果 ecx 大于 ebx 则退出”。将其更改为 jng exit
可解决此问题。
2。堆栈参数
您指的是带有 8(%ebp,%ebx,4)
的参数,但参数实际上是从 12(%ebp)
开始的。你是对的,你应该从索引 1 开始,因为索引 0 的参数只是程序的名称。
3。参数总是字符串
栈上的参数只是指向字符串的指针。 movl 12(%ebp),%eax
不会将命令行中的数字放入 eax
。它只会在 eax 中放入一个内存地址,指向构成第一个参数的一系列字符。
要获得由字符串“123”表示的数字,您需要使用类似atoi 的函数对其进行解析。 .然后 atoi 将在 eax
中返回 123。
修复这些问题后,代码如下所示。我在每个更改的行旁边都添加了注释。
.section .data
.section .text
.global _start
_start:
call adder
movl %eax,%ebx
movl $1,%eax
int $0x80
adder:
pushl %ebp
movl %esp,%ebp
movl $0,%eax #eax = return
movl $1,%ebx #ebx = index
movl 8(%ebp),%ecx #number of args
loop:
cmpl %ebx,%ecx
jng exit # quit if ecx is not greater than ebx
pushl %eax # save registers on stack
pushl %ecx # because they will be destroyed soon
pushl 12(%ebp,%ebx,4) # push next argument pointer on stack
call atoi # invoke atoi, this destroys registers eax,ecx,edx
add $4,%esp # restore stack pointer
mov %eax,%edx # atoi returns the value in eax, save that to edx
popl %ecx # restore ecx from stack
popl %eax # restore eax from stack
addl %edx,%eax # add parsed number to accumulator
incl %ebx
jmp loop
exit:
movl %ebp,%esp
popl %ebp
ret
程序现在似乎可以运行了:
$ gcc -nostartfiles test.S -m32 && ./a.out 1 2 3 4 5 ; echo $?
15
程序在其退出值中返回结果,这意味着它不能计数大于 255 :)
让程序使用 printf
将结果打印到标准输出可能会更好。
关于linux - 简单的加法器不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5427893/