【问题标题】:Convert Instruction in assembly code lods and stos so NASM can compile在汇编代码 lods 和 stos 中转换指令,以便 NASM 可以编译
【发布时间】:2016-10-17 17:16:32
【问题描述】:

好的,所以我正在尝试使用 nasm -f elf final.asm 在程序集中组装一些代码:

xor eax,eax
push eax
push dword(0x75792273)
push dword(0x70742027)
push dword(0x77777875)
push dword(0x20237678)
push dword(0x76727827)
push dword(0x27797175)
push dword(0x75711225)
push dword(0x72747676)
push dword(0x74231476)
push dword(0x70707470)
push dword(0x23247077)
push dword(0x78707822)
push dword(0x24711174)
push dword(0x22707373)
push dword(0x78717974)
push dword(0x75771777)
push dword(0x70777125)
push dword(0x73731472)
push dword(0x71277377)
push dword(0x79251822)
push dword(0x79707478)
push dword(0x78742779)
push dword(0x72727871)
push dword(0x71251475)
push dword(0x27247772)
push dword(0x79757479)
push dword(0x70227071)
push dword(0x77737420)
push dword(0x70251970)
push dword(0x74747127)
push dword(0x23277677)
push dword(0x79712024)
push esp
pop esi
mov edi,esi
mov edx,edi
cld
mov ecx,0x80
mov ebx,0x41
xor eax,eax
push eax
lods byte[esi]
xor eax,ebx
stos byte[es:edi]
loop 0xb7
push esp
pop esi
int 0x3

这会导致以下错误:

final.asm:44: error: parser: instruction expected
final.asm:46: error: parser: instruction expected

我在以下位置找到了这些错误的答案: NASM: parser: instruction expected rep movs

基本上,这表示 lods 和 stos 指令不被 NASM 识别。这意味着我需要将它们转换成 NASM 能够识别的东西,这样我才能得到相同的结果。

我的问题是,我可以将这两行更改为什么,以便 NASM 可以编译它,以便最终调试它。

【问题讨论】:

  • 更改为简单的lodsbstosb(无操作数)。
  • 当我运行它时,我得到:test.asm:44:错误:操作码和操作数的无效组合 test.asm:46:错误:操作码和操作数的无效组合
  • lodsb 字节[esi] stosb 字节[es:edi]
  • 只使用lodsbstosb lodsb byte [esi]
  • 顺便说一句,用lodsb覆盖段使用,NASM中的语法是ss lodsb(我自己很好奇,因为我还不需要它,所以我不得不搜索一段时间才能找到NASM句法)。 stos 系列指令固定为 es 并且不能被覆盖。

标签: assembly nasm


【解决方案1】:

lodsb 所做的是:

mov al,[esi]
inc esi           ; (or dec, according to direction flag)

您也可以使用
lodsw 加载单词(至ax,将esi 增加2),或
lodsd 加载dwords(至eax,增加esi 4)。

stosb 确实如此

mov [es:edi],al
inc edi

同样,stoswstosd 将存储 2 或 4 个字节(并相应调整 edi

首先从 SOURCE (ESI) 寄存器指向的内存中加载,然后写入 DESTINATION (ES:EDI) 寄存器指向的内存。

您不需要(也不能)指定将使用哪些寄存器。源永远是 ESI,目标永远是 EDI


编辑段寄存器: lods 指令可以与段覆盖前缀(即ss lodsb)一起使用。 stos 指令固定为 es(原始答案中缺少详细信息)段使用,并且不能被覆盖。

movsb/movsw/movsd 指令 (size*(mov [es:edi],[ds:esi] inc esi inc edi)) 也可以在源端被覆盖,即。 es movsb 将从es:esi 而不是ds:esi 获取字节,但目标段寄存器固定为es

【讨论】:

  • @Ped7g 当然,使用的寄存器是al ...不是ah!谢谢指正
【解决方案2】:

使用lodsb / lodsw / lodsd / lodsq 用助记符本身表示操作数大小,用操作数。

删除 byte [esi] 部分,NASM 将不接受字符串指令的显式操作数。


Intel's LODS documentation 建议您可以将操作数用作文档并暗示操作数大小(和段覆盖),就像您尝试做的那样,作为操作数大小后缀的替代方案。

提供这种显式操作数形式是为了便于记录;但是,请注意,此表格提供的文件可能会产生误导。也就是说,源操作数符号必须指定操作数(字节、字或双字)的正确类型(大小),但不必指定正确的位置。位置始终由 DS:(E)SI 寄存器指定,必须在执行加载字符串指令之前正确加载。

大概 NASM 语法的设计者认为允许 lods byte [r15] 组合是一个坏主意,并且完全禁止单操作数形式比编写一堆代码只是为了检查给定的操作数是否是它应该的更容易是。

由于 NASM 具有用于段/操作数/地址覆盖的前缀语法,fs lodsb 允许您编写原本需要操作数来附加段覆盖的内容(如 MASM 语法中的 lodsb fs:[rsi]。)

就汇编程序而言,这样做会使字符串指令不特殊;它们只是将助记符映射到操作码的表中的另一个条目。如果英特尔自己的语法包含机器码前缀字节的助记符前缀,他们可能会做出相同的设计选择。

有趣的事实:STOS 的段不能被覆盖(来自 ES)。也许英特尔希望与 MOVS 的原始 8086 实现共享更多晶体管,其中段覆盖仅影响 [DS:SI] 源,而不影响 [ES:DI] 目标。


其他汇编器

GNU .intel_syntax 支持段前缀语法,但不支持 NASM 的 o16/o32/o64a16/a32/a64 操作数和地址大小说明符。

# assembled with as --32    disassembled with ndisasm -b 32
.intel_syntax noprefix

    mov    al, byte ptr fs:[esi]
                    00000038  648A06            mov al,[fs:esi]

    gs lodsb
                    0000003B  65AC              gs lodsb
    lods   dword ptr ss:[ecx]
    # Warning: `dword ptr ss:[ecx]' is not valid here (expected `[esi]')
                    0000003D  36AD              ss lodsd
    ss lodsd   [si]
                    0000003F  3667AD            ss a16 lodsd
    lods   eax, dword ptr ss:[esi]
                    00000042  36AD              ss lodsd

#lods al      # Error: operand type mismatch for `lods'
#fs es lodsd  # Error: same type of prefix used twice
#a16 lodsb    # Error: no such instruction: `a16 lodsb'

我看不到在不使用 GNU 语法(AT&T 或 Intel)中的字符串指令的显式操作数的情况下编写地址大小覆盖的方法。

objdump -Mintel 的输出相同:

   4:   64 8a 06                mov    al,BYTE PTR fs:[esi]
   7:   65 ac                   lods   al,BYTE PTR gs:[esi]
   9:   36 ad                   lods   eax,DWORD PTR ss:[esi]
   b:   36 67 ad                lods   eax,DWORD PTR ss:[si]
   e:   36 ad                   lods   eax,DWORD PTR ss:[esi]

【讨论】:

    猜你喜欢
    • 2011-12-07
    • 1970-01-01
    • 2016-08-02
    • 1970-01-01
    • 2016-05-08
    • 1970-01-01
    • 2011-04-10
    • 2016-01-23
    • 1970-01-01
    相关资源
    最近更新 更多