【问题标题】:Unable to find length of String in Assembly(nasm Linux)无法在程序集中找到字符串的长度(nasm Linux)
【发布时间】:2016-02-06 16:39:25
【问题描述】:

我制作了一个程序,它接受一个字符串作为用户的输入,然后计算它的长度并显示它。但是当我运行程序时,我收到一个错误Segmentation fault (core dumped)。我的代码如下所示

str_len:                    ;Procedure to calculate length of String
    xor rdx,rdx
    xor rcx,rcx             ;I want to store length in rcx
    mov rdx,[string]        ;string contains the input taken from the user
    mov rsi,rdx
    mov rcx,'0'             ;By default rcx will contain '0' decimal

up: cmp byte[rsi],0         ;Compare if end of string
    je str_o                ;If yes then jump to str_o

    inc rcx                 ;Increment rcx i.e., length
    inc rsi                 ;Point to next location of rdx i.e.,string
    jmp up                  ;Repeat till end of string

str_o:  mov rax,1           ;Print final length
        mov rdi,1
        mov rsi,rcx
        mov rdx,1
        syscall
ret

我可以保证我的程序的其余部分是正确的。错误将出现在代码的上述部分。可能是什么错误?

【问题讨论】:

  • sys_write 系统调用写入字符串,而不是数字(或寄存器中的单个字符)。您需要将您的数字转换为字符串并将缓冲区地址(包含转换后的数字)传递给 sys_write。在您的情况下,您必须将 rcx 中的值移动到临时缓冲区,然后将该缓冲区的地址传递给 sys_write。
  • 谢谢,我会试试的
  • 我试过你说的但还是一样的错误
  • 另一个问题是字符串的地址加载不正确。 mov rdx,[string] 正在移动从标签字符串开始的 8 个字节并将它们移动到 reigster 中。你想要string的地址。
  • 我可以保证我的程序的其余部分是正确的。如果我们每次听到这个消息都能得到一美元,我们都会变得富有:)

标签: assembly 64-bit nasm


【解决方案1】:

错误在这里:

mov rdx,[string] ; string contains the input taken from the user

您正在加载带有字符串内容的前 8 个字节的 RDX,而不是字符串的地址。所以更好用

lea rdx, string  ; LEA = Load Effective Address

另一个问题是您的输出例程试图打印一个未转换为 ASCII 的数字

mov rax,1      ; SYS_WRITE - Print final length
mov rdi,1      ; STDOUT handle
mov rsi,rcx    ; RSI should point to buffer
mov rdx,1      ; length of buffer - a value of one prints only one char
syscall

这样不行。您必须先将 RCX 中的 qword 编号转换为 ASCII 字符串,然后在 RSI 中传递该字符串的地址。在 Stack Overflow 上搜索 this 等问题。

【讨论】:

  • lea rdx,string 的问题在于它给出了错误invalid combination of opcode and operands。所以我尝试了lea rdx,[string],但又出现了错误segmentation fault
  • 我也将结果转换为ASCII为add byte[rcx],30h,并使用缓冲区将其打印为mov [strlen],rcx,但没有得到输出。
  • @Paras:嗯,不。将 RCX 中的数字转换为字符串并不像在 CL 中添加 30h 的值那么容易。您也尝试使用 RCX 作为地址 - 这是不正确的。 Here 你会在 32 位汇编中找到一个算法来执行此操作,当然,应该针对 64 位进行修改。
  • @Paras: lea rdx, [rel string] 是正确的。 (或者使用DEFAULT REL 指令,这样您就不需要rel 来获得RIP 相对寻址)。学习使用调试器,这样您就可以找到出现段错误的指令。然后查看正在取消引用的寄存器,并检查它是否包含地址。或者至少告诉我们段错误在哪里。
猜你喜欢
  • 2016-03-05
  • 2011-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-26
  • 2021-12-26
  • 1970-01-01
相关资源
最近更新 更多