Assembly 在yasm中,当目标代码为32位时,如何在jmp附近指定16位?

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位代码(默

我试图让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位代码(默认地址/操作数大小=32)中的选项有:

  • 正常的2字节
    jmp/jcc rel8
    。使用jmp short强制执行
  • 正常的5字节
    jmp rel32
    或6字节
    jcc rel32
    (2字节操作码+4字节rel32)
    jmp dword
    在任何模式下,以及
    jmp near
    在32/64位代码中
  • 4字节
    jmp rel16
    /5字节
    jcc rel16
    的操作数大小前缀,用于将EIP的上16位归零。(不能在64位模式下编码,只能在16位或32位模式下编码。)
    jmp-word
    在16/32位模式下,
    jmp-near
    在16位模式下
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