我试图在不使用标签的情况下跳过1条指令,带标签的例子是:
cmp r12, r13
je dest ; skip the jmp
jmp whatever
dest:
nop
但是,我的限制是我不能使用标签,所以我假设我必须创建一个相对于RIP寄存器的跳转。例如(伪):
cmp r12, r13
je rip+0x05 ; this would obviously depend on the length of the next instruction
jmp whatever
nop
然而,我缺乏生产任何工作的知识,据我所知,没有黑客也无法读/写RIP寄存器。
编辑:我只熟悉英特尔语法,我使用Keystone作为汇编程序。我将从程序集中取出字节并将其加载到可执行内存位置。我正在使用我自己的网站从汇编中获取字节,如果你查看it,你可能会有这个想法。
编辑2:我尝试了Jesters和Margaret Blooms的评论,建议使用:
je .+0x05
; or
je $+0x05
但是,我可以确认两者都不适用于Keystone!幸运的是,我注意到Keystone能够处理这段代码:
je +0x05
是否有人能够确认这是否有效?
编辑3:我用NASM试了一下,$前缀与我测试过的代码配合得很好。我用它来测试它:
section .text
global _WinMain@16
_WinMain@16:
jmp $+2+2 ; skip this jmp and the next jmp (each 2 bytes)
jmp $
ret 16
它按预期工作。同样defuse产生与Keystone相同的输出。唯一的区别是defuse使用$前缀而Keystone根本不需要! Keystone等价物是:
jmp +4
jmp .
ret 16
答案 0 :(得分:3)
请注意,在NASM中,MASM $ docker network inspect otp_bridge
[
{
"Name": "otp_bridge",
"Id": "727bfc6cc21fd74f19eb7fe164582637cbad4c2d7e36620c1c0a1c51c0490d31",
"Created": "2017-12-13T06:12:40.5070258Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.19.0.0/16",
"Gateway": "172.19.0.1"
}
]
},
"Internal": false,
"Attachable": true,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"02fa407062cdd5f6f368f2d17c5e68d2f9155d1d9b30c9edcbb2386a9ded648a": {
"Name": "totp_api",
"EndpointID": "860c47da1e70d304399b42917b927a8cc6717b86c6d1ee6f065229e33f496c2f",
"MacAddress": "02:42:ac:13:00:02",
"IPv4Address": "172.19.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {
"com.docker.compose.network": "bridge",
"com.docker.compose.project": "otp"
}
}
]
不是前缀。 It's a stand-alone keyword / symbol which refers to the address of the current line
$
无法工作:je $+5
为5个字节,短JCC为2.因此,您需要jmp rel32
跳过5字节指令,或{{ 1}}跳过一个2字节的指令。
rel8位移将为je $+7
或$+4
,因为跳转会从指令末尾对其位移进行编码。但是NASM的0x05
标签给出了指令开始的地址,汇编器总是根据目标地址为你计算相对位移。因此,对于0x02
,您需要包含当前指令的长度。
如果您想自己编码rel8,可以使用$
伪指令发出所需的字节。例如$+x
除非您使用可靠的方式知道下一条指令的时长,否则您不使用任何标签的整个方法/目标都存在根本缺陷。 (例如,使用db
或db 0xEB, 0x02
强制执行长编码或短编码)。您所能做的就是编码一个跳转,该跳转前进固定数量的字节,而不是跳过一条指令的跳转,无论宽度如何。
但严重的是只使用标签; x86跳跃总是相对的,所以让你的汇编程序让你的生活更轻松,并计算正确的相对位移。