简单的加法器不起作用

时间:2011-03-25 02:25:12

标签: linux assembly

我用汇编制作了简单的参数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

1 个答案:

答案 0 :(得分:2)

此代码存在一些问题,但您处于正确的轨道上。

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将结果打印到stdout可能会更好。