Как использовать fs:bx в инструкции вызова в Flat Assembler?

Я создаю ядро, и мне нужна помощь с инструкцией вызова. Я использую Flat Assembler для сборки ядра.

call fs:bx

Возможно ли это?
Потому что плоский ассемблер выдает ошибку "неверный размер операнда".

я знаю, что могу сделать

call 1000h:0h

Но это не то, чего я хочу. У кого-нибудь есть ответ на этот вопрос?


person SeeSoftware    schedule 13.08.2016    source источник


Ответы (1)


Я предполагаю, что вы хотите, чтобы call fs:bx установил cs=fs и ip=bx в качестве дальнего вызова.

Косвенные дальние вызовы требуют, чтобы seg:offset находился в памяти, а не в регистрах. См. запись insn ref для 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 в первую очередь для настройки этой инструкции, так что не делайте этого в первую очередь.

person Peter Cordes    schedule 13.08.2016
comment
У меня вопрос: что означает что-либо в вашем примере? - person SeeSoftware; 13.08.2016
comment
@SeeSoftware: это числовая константа, которая зависит от размера кадра стека (т. е. разницы между bp и sp после нажатия fs и bx.) Эквивалентно, вы можете заранее зарезервировать некоторое пространство в стеке своей функции, чтобы вы могли mov [bp - 8], fs / mov [bp - 6], bx / ... / call [bp - 8] - person Peter Cordes; 13.08.2016
comment
на самом деле вы можете просто использовать [sp] вместо [bp-whatever], и у меня это отлично работает, кстати, как вернуться из него? ret или retf или что-то еще РЕДАКТИРОВАТЬ: вы не можете использовать sp напрямую, вы должны поместить его в другой регистр - person SeeSoftware; 14.08.2016
comment
@SeeSoftware: да, 16-битный код имеет раздражающие ограничения на режимы адресации, см. вики тегов x86. И да, нужно делать дальний возврат. Я никогда не писал 16-битный код, который что-то делает с дальними указателями, но я думаю, что дальний вызов просто подталкивает cs:ip туда, где его может вытолкнуть retf. IDK, каков синтаксис FASM для дальнего возврата, но вы можете проверить с помощью дизассемблера, чтобы убедиться, что он сгенерировал 0xCB код операции. Я не фанат 16-битного кода и не рекомендовал бы его как способ изучения ассемблера, если вы еще не знакомы с x86. - person Peter Cordes; 14.08.2016
comment
как исправить/очистить стек после звонка? я не эксперт в стеке и прочем, но я думаю, вам просто нужно увеличить указатель стека? - person SeeSoftware; 14.08.2016
comment
@SeeSoftware: да, если вы вставили 8 байт аргументов, add sp, 8 - person Peter Cordes; 14.08.2016