【问题标题】:summing chars in loop在循环中求和字符
【发布时间】:2014-05-16 05:25:11
【问题描述】:

我正在尝试对循环中的字符串的 ascii 值求和。我想我遗漏了一些东西,但是我总是在程序结束时返回错误的值(即与我使用 ascii 表手动求和的值不匹配),或者是段错误。

我的程序:

.data                           # .data section begins
name: .ascii "Json"             # name is ASCII chars (.ascii or .byte)
len:  .int 4                    # name length is 4 chars, an integer
newline: .ascii "\n"            # new line character

count: .int 0                   # counter for loop (start at 0)

return: .int 0                  # return code value
tmp: .int 0                     # temp value

.text                           # text section starts
.global _start                  # main program entry

_start:                         # start instruction

again:                          # begin loop

    mov $1, %edx                # 1 byte at a time
    mov $name, %ecx             # mem addr
    add count, %ecx             # offset in string

    #### Trouble area ####

    # this seg faults
    mov count(%ecx), %ebx
    add %ebx, return

    #### Trouble area ####

    mov $1, %ebx                # file descriptor 1 is computer display
    mov $4, %eax                # system call 4 is sys_write (output)
    int $128                    # interrupt 128 is entry to OS services

    add $1, count               # incr count
    mov count, %eax             # copy count to eax
    cmp %eax, len               #   and compare values

    jne again                   # if not equal, goto again

    mov $newline, %ecx          # mem addr

    mov $1, %ebx                # file desc 1
    mov $4, %eax                # sys call 4
    int $128                    # interrupt 128

    mov $1, %eax                # system call 1 is sys_exit
    mov return, %ebx            # status return
    int $128                    # interrupt 128

我认为我缺少一些基本的东西,但我理解这是将ecx 寄存器中的值移动count 的值(即循环迭代和数组元素)到寄存器@987654324 @。然后将ebx 中的值添加到return。然后在程序结束时,将return 中的求和值移动到寄存器ebx,然后调用中断。在运行时这个段错误,但我不确定为什么。

我希望它不会出现段错误(显然是大声笑),并且在调用 ~]# echo $? 以打印 410 时(即,'J' + 's' + 'o' + 'n' 或.. . 74 + 115 + 111 + 110)。

UPDATE:------------>

我已根据@Michael 的建议将“问题点”更新为以下内容(如果我理解正确的话)。

    #### Trouble area ####

    # this returns a garbage number, 154 instead of 410
    mov count, %edi 
    mov name(%edi), %ebx
    add %ebx, return

    #### Trouble area ####

【问题讨论】:

  • 我不确定你认为mov count(%ecx), %ebx 做了什么。它将尝试做的是获取count 的地址,添加ecx 的值,从结果地址加载一个32 位值并将其存储在ebx 中。换一种说法;您正在访问 count,就像它是一个数组一样,即使它被声明为单个 int
  • @Michael 谢谢。我的印象是someNumber(%someregister) 使用的是基指针寻址模式,即someNumber 是您在(%someregister) 中的内存地址位置的偏移量。我想我正在尝试像访问数组一样访问它...我尝试使用索引寻址模式,即mov name(,%ecx,1), %edi,但这也不起作用。
  • @Michael 我刚刚发布了对我的原始代码的修订(这次只是有问题的 sn-p。我不再遇到段错误,而是回到获得垃圾输出(错误的数字) .
  • 你说的“输出”是什么意思?您似乎没有在代码中的任何位置打印任何数字。
  • @Michael 抱歉,我的意思是返回值。运行程序后,从终端发出~]# echo $? 应该获取该返回值,即。 410.跨度>

标签: assembly gnu-assembler


【解决方案1】:

退出代码

POSIX 退出状态码实际上是一个无符号字节。

#include <stdio.h>

int main() {
    printf("%d\n", (unsigned char)410);
    return 410;
}

这将打印并返回154,即410 % 256

在此处阅读 POSIX 部分:http://en.wikipedia.org/wiki/Exit_status#POSIX

其他获取价值的方式

  1. 您可以在 gdb 中运行您的进程并使用i r 打印寄存器内容,或使用print return

  2. 您可以将 int 转换为字符串 [1],并在标准输出上调用 write 系统调用 [2],并使用指向结果字符串 (write(1, "string\n", len)) 的指针。

[1] integer to string:mod 10 得到最右边的数字,除以 10 去除最右边的数字,重复直到 n = 0,然后反转字符串 or 致电sprintf()itoa()

[2]http://asm.sourceforge.net/articles/linasm.html#Syscalls

【讨论】:

  • 哇,你是对的。我得到的“垃圾” 154!这是否意味着我需要将我的return 标签更改为.byte 而不是.int?(另外,我不允许要使用 c 库,只能在 GAS 中调用本机 asm)。
  • 您不能以字节为单位返回值 410,其最大值为 255。您可以通过将一些值放入寄存器并执行 int $0x80 来进行 write 系统调用而无需触及 C (你已经为 sys_exit 做了)。这是家庭作业吗?
  • hmm,我需要从程序外部获取值(即echo $?,它从最近运行的程序中获取返回值。将值放入%ebx,然后调用退出程序设置了这个“返回值”。调用int 0x80 我知道会从程序中打印到屏幕上。对不起,我想清楚,但我对 GAS asm 很陌生。
  • 在 Linux 上使用退出状态无法获得大于 255 的值。 int 0x80int $128 相同,只是表示您正在调用系统调用中断。有很多系统调用。
  • 听起来不错,但您仍然无法返回超过 255 的值。我猜想学习状态代码是练习的一部分,或者您的老师没有意识到这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-09
  • 1970-01-01
相关资源
最近更新 更多