Я предполагаю, что вы хотите call fs:bx
установить cs=fs
и ip=bx
, как на дальний звонок.
Косвенные дальние вызовы требуют, чтобы seg: offset находился в памяти, а не регистры. См. the insn ref entry for call
, чтобы подтвердить, что доступно только косвенное far call
- это форма call m16:16
.
Таким образом, в 16-битном коде, вы можете
push fs
push bx
... ; push args
far call [bp-whatever] ; assuming you know the difference between bp and sp at this point
add sp, 4 + arg_size ; clean up args and the far-pointer
Или резервного места на стеке раньше времени, так что вы можете сделать что-то вроде
my_function:
push bp
mov bp, sp
sub sp, 16 ; or whatever size you need for locals. 16 and 8 are just for example.
...
mov [bp - 8], fs
mov [bp - 6], bx ; separately store both parts of fs:bx into [bp-8]
far call [bp - 8]
...
leave
ret
Вы не можете mov cs, fs
или что-нибудь подобное что (даже с использованием регистра GP с нуля). Изменение cs
было бы прыжком, поэтому вам нужно сделать все как одно far call
.
Конечно, вы, вероятно, только поместить значение сегмента в fs
в первую очередь создан для этой команды, так что не делать в первую очередь.
У меня вопрос: что означает «что угодно» в вашем примере? – SeeSoftware
@SeeSoftware: это числовая константа, которая зависит от размера фрейма стека (т. Е. Разница между bp и sp после нажатия fs и bx.) Эквивалентно, вы могли бы зарезервировать некоторое пространство в стеке вашей функции заблаговременно, mov [bp - 8], fs'/'mov [bp - 6], bx'/... /' call [bp - 8] ' –
Фактически вы можете просто использовать [sp] вместо [bp-whatever] и он отлично работает для меня, как вернуться от него? «ret» или «retf» или что-то еще EDIT: вы не можете использовать sp напрямую, вы должны поместить его в другой регистр – SeeSoftware