Assembly 在yasm中,当目标代码为32位时,如何在jmp附近指定16位?
我试图让yasm输出一个16位的近相对jmp。具体来说,它将是一个带有操作数大小覆盖前缀的rel16/rel32 jmp操作码。我知道Assembly 在yasm中,当目标代码为32位时,如何在jmp附近指定16位?,assembly,x86,yasm,Assembly,X86,Yasm,我试图让yasm输出一个16位的近相对jmp。具体来说,它将是一个带有操作数大小覆盖前缀的rel16/rel32 jmp操作码。我知道jmp短标签将发出一个8位的近相对jmp,而jmp长标签将发出一个32位的近相对jmp,但是我如何让它发出一个16位的近相对jmp呢 具体来说,我使用的是位32和cpu i686注意这会将EIP截断为16位IP。 YASM/NASM语法是jmp单词标签。两者都测试过 YASM也错误地允许它处于64位模式1,但NASM仅允许它处于32位和16位模式 32位代码(默
jmp短标签
将发出一个8位的近相对jmp,而jmp长标签
将发出一个32位的近相对jmp,但是我如何让它发出一个16位的近相对jmp呢
具体来说,我使用的是
位32
和cpu i686
注意这会将EIP截断为16位IP。
YASM/NASM语法是jmp单词标签
。两者都测试过
YASM也错误地允许它处于64位模式1,但NASM仅允许它处于32位和16位模式
32位代码(默认地址/操作数大小=32)中的选项有:
- 正常的2字节
。使用jmp short强制执行jmp/jcc rel8
- 正常的5字节
或6字节jmp rel32
(2字节操作码+4字节rel32)jcc rel32
在任何模式下,以及jmp dword
在32/64位代码中jmp near
- 4字节
/5字节jmp rel16
的操作数大小前缀,用于将EIP的上16位归零。(不能在64位模式下编码,只能在16位或32位模式下编码。)jcc rel16
在16/32位模式下,jmp-word
在16位模式下jmp-near
strict
在所有这些覆盖中都是可选的,例如jmp strict short foo
。即使没有严格的限制,如果rel8不能同时达到NASM和YASM,这也不仅仅是一个警告,而是一个错误。我的示例也使用了jmp
,但可以使用ja
、jle
或任何其他jcc
。请注意,它不存在,只有使用相同的覆盖语法的rel16
和rel32
(和间接)
从操作部分:
因此,实际执行与此反汇编匹配,将EIP截断为IP
脚注1:在64位模式下:YASM和binutils bugs vs.real CPU YASM错误地允许它处于64位模式,GNU Binutils错误地将其解码为64位模式下的
jmp rel16
。NASM在64位模式下正确拒绝jmp字
但实际上运行它(在天湖上)会将其解码为jmprel32
,正如英特尔所记录的那样。(在长模式下,rel16
编码被标记为不可编码)
e、 g
汇编+链接到Linux静态可执行文件使用GNU Binutils 2.31.1进行如下反汇编:
0000000000401000 <foo>:
401000: 66 e9 fc ff jmp 1000 <foo-0x400000>
401004: 01 01 add DWORD PTR [rcx],eax
401006: 01 01 add DWORD PTR [rcx],eax
0000000000 401000:
401000:66 e9 fc ff jmp 1000
401004:01 01添加DWORD PTR[rcx],eax
401006:01 01添加DWORD PTR[rcx],eax
在GDB(starti
/si
)中实际运行它表明,我们在从0x1421002
获取代码时出错,即从0x401004+0x0101FFC
获取代码时出错
这与(
66 e9 fc ff 01 01
)忽略无意义的操作数大小前缀,并将其解码为jmp+0x0101ffc
尝试jmp靠近标签
。尝试jmp单词标签
@fuz:这将在16位模式下获得rel16
。在32/64位模式下,jmp near意味着rel32`。使用jmp单词foo
而jmp字节foo
会给出错误,这似乎很奇怪。无论如何,很高兴了解rel16的EIP截断。我对那个文档的理解是绝对目标会被截断,而不是相对目标。老实说,我可能需要做一些测试。似乎对于org0x10000
,yasm应该给出一个错误或警告,说明曾经使用过类似rel16的软件this@Earlz:应用截断的伪代码块位于if abs else rel
块之后,并与块分开。只是为了好玩,我测试了一下工具会说些什么(并进一步确保我的Skylake与文档相符)
# objdump -d -Mintel output from a 32-bit ELF executable
08049000 <foo>:
8049000: 66 e9 fc ff jmpw 9000 <foo-0x8040000>
foo: jmp word foo
db 1, 1, 1, 1
0000000000401000 <foo>:
401000: 66 e9 fc ff jmp 1000 <foo-0x400000>
401004: 01 01 add DWORD PTR [rcx],eax
401006: 01 01 add DWORD PTR [rcx],eax