分段错误movsb nasm在64位linux中

时间:2015-07-22 23:45:08

标签: linux nasm

我是asm的新手,并尝试使用一些操作码来获取它。 我正在研究linux,64位,并且在使用movsb时总是出现分段错误。我用nasm编译:

nasm -f elf64 test.asm

这是代码

DEFAULT ABS
segment data
    data:
    texte: db 'Hello, World !!', 10, 13
    len: equ $-texte
    texteBis: db 'Hello, World !.', 10, 13

segment code
    global main

main:
    ;The problem is here
    mov rsi, texteBis
    mov rdi, texte
    mov cx, len
    rep movsb

    mov dx, len
    mov rcx, texte
    mov bx, 1
    mov ax, 4

    int 0x80

    mov bx,0        ; exit code, 0=normal
    mov ax,1        ; exit command to kernel
    int 0x80        ; interrupt 80 hex, call kernel

其他问题,使用字符串(或其他大型数据库实例),我应该使用

mov rsi, texte

mov rsi, [texte] 

我不明白哪一个给出了价值,哪一个给了地址。

3 个答案:

答案 0 :(得分:1)

你还链接吗?

ld -e main test.o -o test

无论如何,texteBis似乎是数据段中的静态数据。该页面是只读的并受保护以便写入/执行。

如果允许使用运行时库,则应分配缓冲区(在堆栈上或堆上)。

答案 1 :(得分:1)

您的问题是您正在写入写保护内存,即DATA部分。程序加载到内存后,DATA部分实际上是在只读页面上。您必须使用堆栈内存(或动态分配的内存)并将其用作字符串副本的目标。

示例:

sub rsp, len        ; move stack pointer down 'len' bytes
mov rsi, texteBis  
mov rdi, rsp        ; use address of stack pointer as dest.
xor rcx,rcx         ; cx = 0
mov cx, len
rep movsb

那应该可以解决你的问题。与在C中一样,分配足够的空间很重要,否则您将覆盖堆栈上的数据。

将值分配给寄存器

我注意到的另一件事是你经常写寄存器的子部分,例如

mov dx, len

这很危险,因为其他部分不会被此覆盖。仅写入寄存器的最低16位。说rdx,64位值设置为0xffffffffffffffff。移动后rdx看起来像这样:0xffffffffffff0011。调用代码可能完全读取rdx,因此解释0xffffffffffff0011字节的长度。不是你想要的。解决方案:

xor rdx,rdx
mov  dx, len

mov rdx, len

以后可能会帮助您的工具

注意,gdb将帮助您找到错误发生的位置,并且还会为您提供其他信息(例如寄存器值和堆栈值)。摘录:

Program received signal SIGSEGV, Segmentation fault.
0x00000000004005bb in main ()
(gdb) disassemble 
Dump of assembler code for function main:
   0x00000000004005a6:  sub    $0x13,%rsp
   0x00000000004005aa:  mov    -0x1c(%rip),%rsi        # 0x400595
   0x00000000004005b1:  mov    %rsp,%rdi
   0x00000000004005b4:  xor    %cx,%cx
   0x00000000004005b7:  mov    $0x11,%cx
=> 0x00000000004005bb:  rep movsb %ds:(%rsi),%es:(%rdi)
   0x00000000004005bd:  mov    $0x11,%dx
   0x00000000004005c1:  movabs $0x400584,%rcx
   0x00000000004005cb:  mov    $0x1,%bx
   0x00000000004005cf:  mov    $0x4,%ax
   0x00000000004005d3:  int    $0x80
   0x00000000004005d5:  mov    $0x0,%bx
   0x00000000004005d9:  mov    $0x1,%ax
   0x00000000004005dd:  int    $0x80
End of assembler dump.
(gdb) info registers rsi
rsi            0x57202c6f6c6c6548   6278066737626506568

由于nasm不支持有用的调试格式,但通常情况下您希望在某些情况下中断,您可以使用int3指令在SIGTRAP处引发 mov eax, 10 int3 ; debugger will catch signal here 代码中的某一点:

   func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
            return nil
    }

希望这有助于您开始组装。

答案 2 :(得分:1)

您不需要使用动态内存。您的数据段或部分是只读的,因为它不是标准部分,您没有定义它的属性,默认情况下,nasm将它们指定为只读数据部分。

在代码中使用objdump -h输出以下内容:

  0 data          00000022  0000000000000000  0000000000000000  00000200  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 code          0000003c  0000000000000000  0000000000000000  00000230  2**0
              CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA

如果您将分段的名称更改为.data.text,该程序将完美运行并objdump输出:

0 .data         00000022  0000000000000000  0000000000000000  00000200  2**2
              CONTENTS, ALLOC, LOAD, DATA
1 .text         0000003c  0000000000000000  0000000000000000  00000230  2**4
              CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE

您打算使用哪些部分的正确属性。

要了解有关属性的更多信息,请参阅此页面: https://www.tortall.net/projects/yasm/manual/html/objfmt-elf-section.html