我有以下代码:
.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.................................^为什么我会得到这个错误?
发布于 2015-03-15 20:45:19
您的call #0x0似乎在as86中指定了IP (指令指针)-relative调用(相对于下一条指令的偏移量)。这是故意的吗?as86可能会抱怨,因为它期望的是标签或符号,如果需要,链接器将能够解析(重新定位)。
as86手册页包含以下内容:
'Near‘和'far’不允许多段编程,所有'far‘操作都是通过使用以下指令显式指定的: jmpi、jmpf、callf、retf等。'near’运算符可用于强制使用80386个16位条件分支。'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选择英特尔语法和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。
发布于 2015-03-15 18:17:46
我不认为在调用前设置cs是一个好主意,被调用的过程不知道如何返回。你必须执行一个远距离调用,调用段:偏移。这将把ip和cs寄存器的值推入栈以便返回。对于你的代码: call cs:0x00也是一条x86指令吗?
Se this链接
https://stackoverflow.com/questions/29059030
复制相似问题