我有两个汇编代码,如下面的
文件:a.asm
section .text
global _start
_start: mov eax, 4
mov ebx, 1
mov ecx, mesg
mov edx, 10
int 0x80
mov eax, 1
int 0x80
mesg db "KingKong",0xa
和另一个汇编代码
file:b.asm
section .text
global _start
_start: jmp mesg
prgm: mov eax, 4
mov ebx, 1
pop ecx
mov edx, 10
int 0x80
mov eax,1
int 0x80
mesg: call prgm
db "KingKong",0xa
获取这两个代码的十六进制并将其放入此C包装器
之后char *b = "\xb8\x04\x00\x00\x00\xbb\x01\x00\x00\x00\xb9\x7d\x80\x04\x08\xba\x0a\x00\x00\x00\xcd\x80\xb8\x01\x00\x00\x00\xcd\x80\x4b\x69\x6e\x67\x4b\x6f\x6e\x67\x0a";
char *b = "\xe9\x19\x00\x00\x00\xb8\x04\x00\x00\x00\xbb\x01\x00\x00\x00\x59\xba\x0a\x00\x00\x00\xcd\x80\xb8\x01\x00\x00\x00\xcd\x80\xe8\xe2\xff\xff\xff\x4b\x69\x6e\x67\x4b\x6f\x6e\x67\x0a";
int main()
{
(*(int (*)(void))a)();
}
第一个汇编代码(b
)按预期打印'KingKong',但第二个汇编代码a
打印垃圾。像显示的那样
root@bt:~/Arena# ./a
�root@bt:~/Arena#
root@bt:~/Arena# ./b
KingKong
由a
(第一个)生成的输出是这个�
奇怪的字符,而第二个(b
)按预期打印kingkong
。
现在有人可以解释为什么第二个汇编代码工作而第一个汇编代码没有。
修改
从答案我看到第一个程序硬编码地址。即使第二种方法使用标签,如jmp mesg
,现在这条指令不会使程序与第一种程序非常相似,并不是它们都使用labels
来确定位置。我所知道的是,为了使代码位置独立,我们需要使用esp
或ebp
寄存器和相对寻址方案。第二个程序的jmp指令不会像第一个程序那样使用它。
答案 0 :(得分:7)
mesg
的地址可能会有所不同,具体取决于您的计划在内存中的布局方式。
以下内容将对特定地址进行硬编码,并且无法可靠地(或根本不)使用:
mov ecx, mesg
作为参考,第一种方法硬编码以下地址:
mov ecx, 0x804807d
第二种方法确实有效,因为它使用mesg
指令的返回地址在运行时计算出call
的地址。
换句话说,第一个版本只有在特定地址加载时才有效,而第二个版本只有position-independent。
值得注意的是,第二版中出现的jmp
和call
指令使用相对寻址,这意味着操作码指定距离< / em>到目标而不是目标的地址。这使得这些指令无论在内存中的位置如何都可以正常工作。
如果检查操作码,您会看到jmp
编码为
e9 19 00 00 00
(即跳转0x19,或25 10 ,字节向前),call
编码为
e8 e2 ff ff ff
其中0xffffffe2
是一个小的负数(-30)。