Search code examples
assemblyx86kernelfasm

How do i use fs:bx in call instruction at Flat Assembler?


I am creating a Kernel and I need some help with the call instruction. I am using Flat Assembler to build the Kernel.

call fs:bx

Is that possible ?
Because flat assembler gives me an "invalid size of operand" Error.

I know I can do

call 1000h:0h

But that is not what I want. Does someone have the answer to this question?


Solution

  • I'm assuming you want call fs:bx to set cs=fs and ip=bx, as a far call.

    Indirect far calls require the seg:offset to be in memory, not registers. See the insn ref entry for call to confirm that the only available indirect far call is the call m16:16 form.

    So in 16-bit code, you could

    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
    

    Or reserve space on the stack ahead of time so you can do something like

    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
    

    You can't mov cs, fs or anything like that (even using a scratch GP register). Changing cs would be a jump, so you have to do the whole thing as one far call.


    Of course, you probably only put the segment value in fs in the first place to set up for this instruction, so don't do that in the first place.