Используется push / push / ret far
в качестве jmp для абсолютного смещения в переменном целевом сегменте.Он извлекает новый CS: IP из стека, в данном случае ES:SECONDRELOC
.
На самом деле, они хотят попасть в функцию RE_INIT
с «поддельным» обратным адресом CS: IP.
x86 имеет jmp ptr16:16
, который может перейти к абсолютному сегменту: off, но он работает только с жестко закодированным сегментом и смещением.Таким образом, единственный способ сделать дальний переход (установка новой CS, а также IP) с сегментом и / или смещением переменной времени выполнения - это иметь оба в памяти для jmp [m16:16]
или для стека для ret far
чтобы вытащить их обоих.
Чтобы прыгать, не оставляя вещи в стеке и не резервируя какие-либо статические данные, far ret - единственный хороший вариант.(Существует также плохая опция самоизменения кода для изменения части сегмента jmp 0000:SECONDRELOC
перед его выполнением, но это, вероятно, хуже для размера кода.)
Они mov
значениесначала в AX, вместо использования push OFFSET SECONDRELOC
напрямую, потому что push imm8
и push imm16
были добавлены только в 286. (См. приложение к старой версии руководства NASM: http://www.posix.nl/linuxassembly/nasmdochtml/nasmdoca.html. Поиск"push imm" на этой странице.)
Это то же самое, что и в коде, который вы показали в Какова цель PUSH CS / POP DS перед REP MOVSW? ,где я уже описал, как код выдвигает seg:off
, а затем использует дальний ret
для перехода к новому CS: IP.