Я пытаюсь сделать относительный переход в сборке x86, однако не могу заставить его работать. Кажется, по какой-то причине мой прыжок продолжает переписываться как абсолютный прыжок или что-то в этом роде.
Простой пример программы, которую я пытаюсь сделать, таков:
.global main
main:
jmp 0x4
ret
Поскольку инструкция jmp имеет длину 4 байта и относительный переход смещен относительно адреса перехода + 1, это должно быть необычным запретом. Однако компиляция и запуск этого кода вызовет ошибку сегментации.
Настоящая загадка для меня заключается в том, что компиляция его на уровне объекта и последующая разборка объектного файла показывают, что похоже, что ассемблер правильно выполняет относительный переход, но после компиляции файла компоновщик меняет его на другой тип. прыжка
Например, если приведенный выше код был в файле asmtest.s:
$gcc -c asmtest.s
$objdump -D asmtest.o
... Some info from objdump
00000000 <main>:
0: e9 00 00 00 00 jmp 5 <main+0x5>
5: c3 ret
Похоже, ассемблер правильно сделал относительный переход, хотя подозрительно, что инструкция jmp заполнена нулями.
Затем я использовал gcc, чтобы связать его, затем разобрал его и получил это:
$gcc -o asmtest asmtest.o
$objdump -d asmtest
...Extra info and other disassembled functions
08048394 <main>:
8048394: e9 6b 7c fb f7 jmp 4 <_init-0x8048274>
8048399: c3 ret
Мне кажется, что компоновщик переписал оператор jmp или заменил 5 на другой адрес.
Итак, мой вопрос сводится к тому, что я делаю не так?
Я неправильно указываю смещение? Я неправильно понимаю, как работают относительные прыжки? Gcc пытается убедиться, что я не делаю опасных вещей в своем коде?