c - 在 x86 Assembly 中组装代码时出错

标签 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.................................^

为什么会出现此错误?

最佳答案

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

as86 手册页具有以下内容:

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.

如果我改用 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 生成一个与你正在尝试做的相同的相对调用(不确定这是否有意义 - 你可能会从任何 IP 获得随机位恰好是),那么您可以执行以下操作:

eseg
call zero_offset
zero_offset: pop bx

输出是

  53:   26 e8 00 00             es call 0x57

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

关于c - 在 x86 Assembly 中组装代码时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29059030/

相关文章:

c - 内存分配头是否需要对齐 union ?

c - C中的字符串反转

assembly - 如果 nasm 代码遇到 _start 结尾,是否会自动移动到下一个标签?

c - ARM 汇编中的段错误

c++ - 测试 256 位 YMM AVX 寄存器元素是否等于或小于零的最有效方法

c - 如何分析 C 程序的内存使用情况

c++ - 通过 x86 程序集(嵌入在 C++ 中)对数组进行排序?可能的?

linux - 可以在不同的 CPU 内核上执行相同网络数据包的硬和软 IRQ 吗?

x86 - 冲突检测指令如何使循环矢量化变得更容易?

从不同纤程调用需要主线程的函数