Your call #0x0
seems to specify an IP (Instruction Pointer)-relative call in as86 (an offset relative to the next instruction). Was that intentional? as86 might be complaining because it expected a label or a symbol instead, which the linker would be able to resolve (relocate) if needed.
The as86 man page has the following:
The 'near and 'far' do not allow multi-segment programming, all 'far'
operations are specified explicitly through the use of the instructions: jmpi,
jmpf, callf, retf, etc. The 'Near' operator can be used to force the use of
80386 16bit conditional branches. The 'Dword' and 'word' operators can control
the size of operands on far jumps and calls.
The code assembles if I use callf 0x12345678,0x1234
instead, which generates the following instructions:
$ as86 a.asm -o a.o
$ objdump -D -b binary -mi386 -Maddr16,data16,intel a.o
...
3b: 8e cb mov cs,bx
3d: 8e c3 mov es,bx
3f: 26 66 9a 78 56 34 12 es call 0x1234:0x12345678
46: 34 12
48: 5b pop bx
48: 5b pop %bx
...
(-b binary
it needed since it's raw code, -mi386
selects the instruction set, and -Maddr16,data16,intel
selects Intel syntax and 16-bit code, which seems to be what as86 generates by default.)
The second operand to callf
seems to be the segment selector part of the address (having a single operand to callf
causes as86 to complain). My x86-fu is too weak to say if the segment override on the call actually makes sense there. You'd want callf #0x0,#0x0
in your code, of course.
If you want to "trick" as86 into generating a relative call
that's identical to what you're trying to do (not sure if this makes sense -- you might get random bits from whatever IP happens to be), then you could do the following:
eseg
call zero_offset
zero_offset: pop bx
The output is
53: 26 e8 00 00 es call 0x57
, where the 00 00
part shows that the offset is 0.