Как на самом деле указать линковщику (ld) формат выходного файла?

На самом деле это единственный раздел про unix на этом форуме

Модераторы: /dev/random, Модераторы разделов

Аватара пользователя
жучара
Сообщения: 1008
ОС: астралинукс

Как на самом деле указать линковщику (ld) формат выходного файла?

Сообщение жучара »

Друзья! DEBIAN 12 64, код на ассемблере должен быть 32-х битным.

Код: Выделить всё

global _start           ; делаем метку метку _start видимой извне
 
section .data   ; секция данных
message: db "Hello, word!",10  ; строка для вывода на консоль
 
section .text           ; объявление секции кода
_start:                 ; объявление метки _start - точки входа в программу
    mov eax, 1          ; 1 - номер системного вызова функции write
    mov edi, 1          ; 1 - дескриптор файла стандартного вызова stdout
    mov esi, message    ; адрес строки для вывод
    mov edx, 13         ; количество байтов
    syscall             ; выполняем системный вызов write
 
    mov eax, 60         ; 60 - номер системного вызова exit
    syscall             ; выполняем системный вызов exit
Сперва делаю объектный файл, потом исполняемый.

Shell

$ nasm -f elf32 hello.asm
$ ld --oformat=elf32-i386 -o hello hello.o
ld: архитектура i386 входного файла «hello.o» несовместима с выходным i386:x86-64
$
Странно всё это. man ld:
...
--oformat=output-format
ld may be configured to support more than one kind of object file. If your ld is configured
this way, you can use the --oformat option to specify the binary format for the output object
file. Even when ld is configured to support alternative object formats, you don't usually need
to specify this, as ld should be configured to produce as a default output format the most usual
format on each machine. output-format is a text string, the name of a particular format
supported by the BFD libraries. (You can list the available binary formats with objdump -i.)
The script command "OUTPUT_FORMAT" can also specify the output format, but this option overrides
it.
...

То есть нужные нам форматы надо посмотреть так:

Shell

$ objdump -i
Файл заголовка BFD версия (GNU Binutils for Debian) 2.40
elf64-x86-64
(заголовок от младшего к старшему, данные от младшего к старшему)
i386
elf32-i386
(заголовок от младшего к старшему, данные от младшего к старшему)
i386
elf32-iamcu
(заголовок от младшего к старшему, данные от младшего к старшему)
iamcu
elf32-x86-64
(заголовок от младшего к старшему, данные от младшего к старшему)
i386
pei-i386
(заголовок от младшего к старшему, данные от младшего к старшему)
i386
pe-x86-64
(заголовок от младшего к старшему, данные от младшего к старшему)
i386
pei-x86-64
(заголовок от младшего к старшему, данные от младшего к старшему)
i386
elf64-little
(заголовок от младшего к старшему, данные от младшего к старшему)
i386
iamcu
elf64-big
(заголовок от старшего к младшему, данные от старшего к младшему)
i386
iamcu
elf32-little
(заголовок от младшего к старшему, данные от младшего к старшему)
i386
iamcu
elf32-big
(заголовок от старшего к младшему, данные от старшего к младшему)
i386
iamcu
pe-bigobj-x86-64
(заголовок от младшего к старшему, данные от младшего к старшему)
i386
pe-i386
(заголовок от младшего к старшему, данные от младшего к старшему)
i386
pdb
(заголовок от младшего к старшему, данные от младшего к старшему)
srec
(заголовок байтовый порядок неизвестен, данные байтовый порядок неизвестен)
i386
iamcu
symbolsrec
(заголовок байтовый порядок неизвестен, данные байтовый порядок неизвестен)
i386
iamcu
verilog
(заголовок байтовый порядок неизвестен, данные байтовый порядок неизвестен)
i386
iamcu
tekhex
(заголовок байтовый порядок неизвестен, данные байтовый порядок неизвестен)
i386
iamcu
binary
(заголовок байтовый порядок неизвестен, данные байтовый порядок неизвестен)
i386
iamcu
ihex
(заголовок байтовый порядок неизвестен, данные байтовый порядок неизвестен)
i386
iamcu
plugin
(заголовок от младшего к старшему, данные от младшего к старшему)

elf64-x86-64 elf32-i386 elf32-iamcu elf32-x86-64 pei-i386 pe-x86-64
i386 elf64-x86-64 elf32-i386 ----------- elf32-x86-64 pei-i386 pe-x86-64
iamcu ------------ ---------- elf32-iamcu ------------ -------- ---------

pei-x86-64 elf64-little elf64-big elf32-little elf32-big
i386 pei-x86-64 elf64-little elf64-big elf32-little elf32-big
iamcu ---------- elf64-little elf64-big elf32-little elf32-big

pe-bigobj-x86-64 pe-i386 pdb srec symbolsrec verilog tekhex binary
i386 pe-bigobj-x86-64 pe-i386 --- srec symbolsrec verilog tekhex binary
iamcu ---------------- ------- --- srec symbolsrec verilog tekhex binary

ihex plugin
i386 ihex ------
iamcu ihex ------
$
Странный какой-то вывод, ну да что уж есть. Пытаюсь слинковать с правильным выходным форматом.

Shell

$ ld --oformat=elf32-i386 -o code code.o
ld: архитектура i386 входного файла «code.o» несовместима с выходным i386:x86-64
$
$ ld --oformat=elf32-little -o code code.o
ld: архитектура i386 входного файла «code.o» несовместима с выходным i386:x86-64
$
ЧЯДНТ? Спасибо, кто откликнется.
Последний раз редактировалось жучара 27.07.2024 21:47, всего редактировалось 1 раз.
Я просто читаю маны.
Спасибо сказали:
Аватара пользователя
ormorph
Сообщения: 2804
ОС: Gentoo

Re: Как на самом деле указать линковщику (ld) формат выходного файла?

Сообщение ormorph »

Всё не в тему. Команды для 64 битного процессора. Для 32 бит syscall не используется и номера системных вызовов другие, остальное не помню. Смотреть /usr/include/asm/unistd_32.h. Аргументы вроде тоже в другие регистры ebx, ecx, edx.
Спасибо сказали:
Аватара пользователя
жучара
Сообщения: 1008
ОС: астралинукс

Re: Как на самом деле указать линковщику (ld) формат выходного файла?

Сообщение жучара »

ormorph писал(а):
27.07.2024 14:51
Всё не в тему. Команды для 64 битного процессора. Для 32 бит syscall не используется и номера системных вызовов другие, остальное не помню. Смотреть /usr/include/asm/unistd_32.h. Аргументы вроде тоже в другие регистры ebx, ecx, edx.
а nop там используется?

Код: Выделить всё

global _start           ; делаем метку метку _start видимой извне
section .text           ; объявление секции кода
_start:                 ; объявление метки _start - точки входа в программу
	nop

Shell

$ nasm -f elf32 hello.asm
user@debian:~/Desktop/www/_1$ ld --oformat=elf32-i386 -o hello hello.o
ld: архитектура i386 входного файла «hello.o» несовместима с выходным i386:x86-64
$
А вообще что происходит?

Код: Выделить всё

global _start           ; делаем метку метку _start видимой извне
section .text           ; объявление секции кода
_start:                 ; объявление метки _start - точки входа в программу

Shell

$ nasm -f elf32 hello.asm
user@debian:~/Desktop/www/_1$ ld --oformat=elf32-i386 -o hello hello.o
ld: архитектура i386 входного файла «hello.o» несовместима с выходным i386:x86-64
$
Добавлено (22:08):
Вот так, кстати говоря, собирается, но не запускается. Странно всё это.

Shell

$ nasm -f elf32 hello.asm
$ ld -m elf_i386 -s -o hello hello.o
$ ./hello
bash: ./hello: не удаётся запустить бинарный файл: Ошибка формата выполняемого файла
$
$ nasm -f elf32 hello.asm
$ ld -m elf_i386 --oformat=elf32-i386 -s -o hello hello.o
$ ./hello
bash: ./hello: не удаётся запустить бинарный файл: Ошибка формата выполняемого файла
$
Я просто читаю маны.
Спасибо сказали:
Аватара пользователя
ormorph
Сообщения: 2804
ОС: Gentoo

Re: Как на самом деле указать линковщику (ld) формат выходного файла?

Сообщение ormorph »

жучара писал(а):
27.07.2024 21:53
ld --oformat=elf32-i386 -o hello hello.o
Смотреть в сторону эмуляции ключик -m
ld: поддерживаемые эмуляции: elf_x86_64 elf32_x86_64 elf_i386 elf_iamcu
И того:

Shell

$ nasm -f elf32 hello.asm
$ ld -m elf_i386 -o hello hello.o
Остальные ошибки я уже сказал. Все секции кода правильные, неправильные номера системных вызовов, регистры в которые добавляются параметры системного вызова и т.д. Этот код 64 битный. Файл в котором прописаны номера системных вызовов для 32 битной системы я уже указывал.
Спасибо сказали:
Аватара пользователя
жучара
Сообщения: 1008
ОС: астралинукс

Re: Как на самом деле указать линковщику (ld) формат выходного файла?

Сообщение жучара »

ormorph писал(а):
27.07.2024 22:19
жучара писал(а):
27.07.2024 21:53
ld --oformat=elf32-i386 -o hello hello.o
Смотреть в сторону эмуляции ключик -m
ld: поддерживаемые эмуляции: elf_x86_64 elf32_x86_64 elf_i386 elf_iamcu
И того:

Shell

$ nasm -f elf32 hello.asm
$ ld -m elf_i386 -o hello hello.o
Остальные ошибки я уже сказал. Все секции кода правильные, неправильные номера системных вызовов, регистры в которые добавляются параметры системного вызова и т.д. Этот код 64 битный. Файл в котором прописаны номера системных вызовов для 32 битной системы я уже указывал.
я там выше написал, оно теперь не запускается.
Я просто читаю маны.
Спасибо сказали:
Аватара пользователя
ormorph
Сообщения: 2804
ОС: Gentoo

Re: Как на самом деле указать линковщику (ld) формат выходного файла?

Сообщение ormorph »

жучара писал(а):
27.07.2024 22:48
я там выше написал, оно теперь не запускается.
Само собою оно не будет запускаться, так как сам код не переписан под 32 битный nasm. У вас же всё прописано в комментариях(номера параметров), регистры я уже указал в которые добавляются параметры(слева на право по порядку). Номер системного вызова для 32 битного процессора будет другим, но он так же добавляется в регистр ax. А вот syscall нужно заменить на int 0x80. И того нужно сделать исправления в шести строчках.

Код: Выделить всё

write(int fd, const void *buf, size_t count);
        ebx               ecx         edx 
Спасибо сказали:
Аватара пользователя
жучара
Сообщения: 1008
ОС: астралинукс

Re: Как на самом деле указать линковщику (ld) формат выходного файла?

Сообщение жучара »

ormorph писал(а):
27.07.2024 23:15
жучара писал(а):
27.07.2024 22:48
я там выше написал, оно теперь не запускается.
Само собою оно не будет запускаться, так как сам код не переписан под 32 битный nasm. У вас же всё прописано в комментариях(номера параметров), регистры я уже указал в которые добавляются параметры(слева на право по порядку). Номер системного вызова для 32 битного процессора будет другим, но он так же добавляется в регистр ax. А вот syscall нужно заменить на int 0x80. И того нужно сделать исправления в шести строчках.

Код: Выделить всё

write(int fd, const void *buf, size_t count);
        ebx               ecx         edx 
вы не поняли, вот это не запускается.

Код: Выделить всё

global _start           ; делаем метку метку _start видимой извне
section .text           ; объявление секции кода
_start:                 ; объявление метки _start - точки входа в программу
Я просто читаю маны.
Спасибо сказали:
Аватара пользователя
жучара
Сообщения: 1008
ОС: астралинукс

Re: Как на самом деле указать линковщику (ld) формат выходного файла?

Сообщение жучара »

Это ладно, а вот оно собирается на 32-х битной машине в 32-двухбитном режиме и там же не запускается. Вот это да.

Shell

$ uname -a
Linux debian 6.1.0-22-686-pae #1 SMP PREEMPT_DYNAMIC Debian 6.1.94-1 (2024-06-21) i686 GNU/Linux
$
$ cat hello.asm
bits 32
global _start
section .text
_start:
$
$ nasm -f elf32 hello.asm
$
$ ld -m elf_i386 --oformat=elf32-i386 -s -o hello hello.o
$
$ ./hello
bash: ./hello: не удаётся запустить бинарный файл: Ошибка формата выполняемого файла
$
Я просто читаю маны.
Спасибо сказали:
Аватара пользователя
ormorph
Сообщения: 2804
ОС: Gentoo

Re: Как на самом деле указать линковщику (ld) формат выходного файла?

Сообщение ormorph »

жучара писал(а):
28.07.2024 03:12
$ cat hello.asm
bits 32
global _start
section .text
_start:
И как оно должно выполняться, если секция кода пустая? Хотя бы выход из программы допишите:

Код: Выделить всё

global _start
section .text
_start:
    mov eax, 1
    int 0x80
Спасибо сказали: