首页 > 解决方案 > 将寄存器值移动到节数据中的内存变量

问题描述

我需要帮助将值从寄存器移动到内存,但每次运行代码时都会出现段错误。目标是将 M 分配给 J + K - 1。

section data:
    M dw 0
    J dw 3
    K dw 4

section text:

    global _start

    ; Show how this statement M= J+K -1 could be translated into assembly code using 8086 instruction set.
    ; Assume M, J and K are memory variables. In 8086 assume 16-bit, we can use MOV
    ; instruction to copy the variable into register ex: MOV AX, J.

    _start:
        mov bx, [K] ; move K into bx
        sub bx, 1 ; subtract 1 from bx
        mov ax, [J] ; move J into ax
        add ax, bx ; add J + (K - 1)
        mov [M], ax ; move ax value into M. This is where the seg fault occurs.

        mov rax, 60
        mov rdi, 0
        syscall

标签: assemblyx86nasm

解决方案


链接器不知道称为data:or的部分text:,它们只是随机的自定义部分名称,并且您没有为它们设置权限(读/写/执行)。(:在标签之后使用,而不是部分名称)

你想要section .data并且section .text

(另外,我建议default rel您因为您希望 NASM 使用 RIP 相对寻址来处理类似的地址[K]。)


nasm -felf64 foo.asm && ld -o foo foo.o在我的 Arch Linux 桌面上构建静态可执行文件后,

$ readelf -a foo
...
Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000001000 0x0000000000401000 0x0000000000401000
                 0x0000000000000031 0x0000000000000031  R      0x1000

 Section to Segment mapping:
  Segment Sections...
   00     data: text: 

...

所以我们可以看到text:data:部分都链接了一个只读的不可执行的程序段,所以第一条指令的代码获取_start会出错。或者至少你会期望它会,但是在 GDB 下单步执行它直到它尝试存储回内存时才出现段错误,并且由于它只读映射的,所以出现了错误。

是的,:部分名称末尾的 确实确实出现在目标文件中。


推荐阅读