在x86汇编中组装代码时出错

时间:2015-03-15 09:13:16

标签: c assembly x86 as86

我有以下代码:

.global _launchProgram
_launchProgram:
push bp
mov bp, sp
push cs
mov bx, [bp + 4]
mov cs, bx
mov es, bx
eseg
call #0x0
pop bx
mov cs, bx
pop bp
ret

在这段代码中,我试图让它跳转到另一段代码并执行它。这个代码是从C调用的,如下所示:

launchProgram(segment) //Here segment is an integer which holds the 
                       //memory segment where I have loaded my code

因此在这个函数中我使cs寄存器等于段变量,并使用call 0x0跳转到该段的开头。但是当我使用:

运行它时
as86 launchProgram.asm -o launchProgram.o

我收到以下错误:

00010 000C           E8         0000            call #0x0
***** relocation impossible.................................^

为什么我收到此错误?

2 个答案:

答案 0 :(得分:1)

您的call #0x0似乎在as86中指定了一个IP(指令指针) - 相对调用(相对于下一条指令的偏移量)。这是故意的吗? as86可能会抱怨,因为它需要一个标签或符号,如果需要,链接器可以解析(重新定位)。

as86手册页包含以下内容:

  

'near'和'far'不允许多段编程,所有'远'   通过使用指令明确指定操作:jmpi,   jmpf,callf,retf等.'Near'运算符可用于强制使用   80386 16bit条件分支。 'Dword'和'word'操作符可以控制   跳远和呼叫的操作数大小。

如果我改为使用callf 0x12345678,0x1234代码,则会生成以下指令:

$ 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需要它,因为它是原始代码,-mi386选择指令集,-Maddr16,data16,intel选择Intel语法和16位代码,这似乎是as86默认生成的。)

callf的第二个操作数似乎是地址的段选择器部分(对callf有一个操作数会导致as86抱怨)。我的x86-fu太弱了,无法说出通话中的段覆盖是否真的有意义。当然,您需要在代码中使用callf #0x0,#0x0

如果你想“欺骗”as86生成一个相对call,它与你想要做的相同(不确定这是否有意义) - 你可能从任何IP碰巧得到随机位),那么你可以做到以下几点:

eseg
call zero_offset
zero_offset: pop bx

输出

  53:   26 e8 00 00             es call 0x57

,其中00 00部分显示偏移为0。

答案 1 :(得分:0)

我不认为在通话前设置cs是一个好主意,被叫程序不知道如何返回。你必须执行一个远程呼叫, 呼叫段:偏移量。这将推送堆栈上的ip和cs寄存器的值以返回。对于你的代码类似:call cs:0x00 esag是x86指令吗?

Se this链接

相关问题