Перемещение значений регистров в переменные памяти в разделе данные

#assembly #x86 #nasm

# #сборка #x86 #nasm

Вопрос:

Мне нужна помощь в перемещении значения из регистра в память, но каждый раз, когда я запускаю свой код, я получаю ошибку seg. Цель состоит в том, чтобы присвоить 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
 

Комментарии:

1. Комментарии к коду предполагают, что это 16-разрядный код, но системный вызов предполагает, что вы разместили 64-разрядный код. Вы пишете для 16-разрядной или 64-разрядной версии?

2. А M, J и K, по-видимому, являются 32-битными значениями (dw).

3. @RudyVelthuis: dw имеет ширину 1 слово; 32-разрядный dd . В терминологии x86 «слово» состоит из 16 бит. Код правильный, за исключением названий разделов, просто очень странный (использование 16-битных целых чисел в 64-битном режиме с [disp32] режимами абсолютной адресации, потому что он опускается default rel ). Также неэффективно, потому что он не использует [J] в качестве источника памяти операнд для add ..

4. @PeterCordes: <facepalm> . Я действительно знаю это. Моя защита: я еще не пил кофе. <g>

Ответ №1:

Компоновщик не знает о разделах, вызываемых data: or text: , это просто случайные пользовательские имена разделов, и вы не установили для них разрешение (чтение / запись / выполнение). (Используйте : после меток, а не имен разделов)

Вы хотите section .data и section .text

(Кроме того, я бы рекомендовал default rel , потому что вы хотите, чтобы NASM использовал адресацию RIP-relative для таких адресов, как [K] .)


После создания статического исполняемого файла с nasm -felf64 foo.asm amp;amp; 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 он не выполнял segfault, пока не попытался сохранить обратно в память, и это не сработало, потому что оно отображается только для чтения.

И да, что : имена разделов в конце действительно появлялись в объектном файле.