#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, пока не попытался сохранить обратно в память, и это не сработало, потому что оно отображается только для чтения.
И да, что :
имена разделов в конце действительно появлялись в объектном файле.