NASM x86 - линковщик ругается на обращение к элементам строки
Моё задание - ксорить файл 4-байтным ключом. Вот код:
section .bss
buff resb 4
fd resb 1
sum resb 8
temp resb 1
section .data
gamma db '#0ja', 0xA
O_RDONLY equ 0
O_WRONLY equ 1
O_RDWR equ 2
section .text:
global _start
_start:
pop ebx
pop ebx
pop ebx ;got the name
mov eax, 5
mov ecx, O_RDONLY ;open
mov edx, 0777
int 0x80
mov [fd], eax ;save the desc
loloper:
mov ecx, 4
xor esi, esi
looper:
push ecx
mov eax, 3
mov ebx, [fd]
mov ecx, buff ;get 1 byte
mov edx, 1
int 0x80
mov bl, 0; if end of file
cmp al, bl
jz exit
mov dl, byte [gamma + si]
mov cl, byte [buff + si]
xor dl, cl
mov byte [buff + si], dl
inc si
pop ecx
loop looper
mov eax, 19
mov ebx, [fd]
mov ecx, -4
mov edx, 1
int 0x80
mov bl, 0
cmp cl, bl
jz loloper
exit:
mov eax, 6
mov ebx, [fd]
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
Я делал такое ранее, под DOS, и всё работало, но сейчас, при сборке через
nasm -felf32 1.asm
ld -m elf_i386 1.o -o 1
мне выдаются ошибки:
1.o: In function `looper':
1.asm:(.text:+0x3f): relocation truncated to fit: R_386_16 against `.data'
1.asm:(.text:+0x44): relocation truncated to fit: R_386_16 against `.bss'
1.asm:(.text:+0x4b): relocation truncated to fit: R_386_16 against `.bss'
возможно, такое обращение к области памяти недопустимо в 32-битном асм?
Ответы (1 шт):
mov dl, byte [gamma + si]
В x86 нет варианта относительной адресации, когда к 16-битному регистру прибавляется 32-битное смещение ([reg16 + disp32]). Есть только [reg32 + disp8/32] и [reg16 + disp8/16]. Поэтому ассемблер считает, что [gamma + si] — это [reg16 + disp16] и соответственно резервирует под gamma только 2 байта в команде.
Когда позже линкер пытается это слинковать он видит, что адрес этого символа в секции .data выходит за границы первого мегабайта и справедливо выдаёт ошибку, что он не помещается в отведённые 16 бит.
Собственно здесь и далее надо использовать 32-х битный регистр esi:
mov dl, byte [gamma + esi]