我用汇编制作了简单的参数adder,但它没有工作
它总是返回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
答案 0 :(得分:2)
此代码存在一些问题,但您处于正确的轨道上。
您正在使用此功能在ebx >= ecx
:
cmpl %ebx,%ecx
jg exit
语法相当混乱,但这实际上意味着“如果ecx大于ebx则退出”。将其更改为jng exit
可解决此问题。
您指的是8(%ebp,%ebx,4)
的参数,但参数实际上从12(%ebp)
开始。你应该从索引1开始,因为索引为0的参数只是程序的名称。
堆栈上的参数只是指向字符串的指针。 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
将结果打印到stdout可能会更好。