好的,我正在尝试使用 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
基本上,这表明NASM不承认lods和stos指令 . 这意味着我需要将它们转换为NASM确实识别的内容,以便获得相同的结果 .
我的问题是,我可以更改这两行,以便NASM可以编译它,以便我最终可以调试它 .
2 回答
lodsb
的作用是:你也可以用
lodsw
加载单词(到ax
,将esi
加2),或者lodsd
加载dwords(至eax
,将esi
加4) .和
stosb
同样在这里,
stosw
和stosd
将存储2或4个字节(并相应地调整edi
)首先从内存加载,由SOURCE(ESI)寄存器指向,后者写入DESTINATION(ES:EDI)寄存器指向的内存 .
您不需要(也不能)指定将使用哪些寄存器 . 来源永远是E S 我,而目的地总是E D 我
在段寄存器上编辑:
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
.使用
lodsb
/lodsw
/lodsd
/lodsq
用助记符本身表示操作数大小,而不是操作数 .Remove the byte [esi] part, NASM won't accept explicit operands for string instructions.
Intel's LODS documentation建议您可以使用操作数作为文档,并暗示操作数大小(和段覆盖),就像您尝试做的那样,作为操作数大小后缀的替代 .
据推测,NASM语法的设计者决定允许
lods byte [r15]
汇编是一个坏主意,完全不允许单操作数形式比编写一堆代码更容易,只是为了检查给定的操作数是否应该是它应该是什么 .由于NASM具有用于段/操作数/地址覆盖的前缀语法,
fs lodsb
允许您编写原本需要操作数来附加段覆盖的内容(如MASM语法中的lodsb fs:[rsi]
) .就汇编程序而言,这样做会使字符串指令非特殊;它们只是将表格助记符映射到操作码的表中的另一个条目 . 如果英特尔自己的语法包含机器代码前缀字节的助记符前缀,那么它们可能已经做出了相同的设计选择 .
有趣的事实:STOS 's segment can' t被覆盖(来自ES) . 也许英特尔希望与原始的8086实现MOVS共享更多晶体管,其中段覆盖仅影响
[DS:SI]
源,而不影响[ES:DI]
目的地 .other assemblers :
GNU
.intel_syntax
支持段前缀语法,但不支持NASM的o16
/o32
/o64
或a16
/a32
/a64
操作数和地址大小说明符 .我没有看到在GNU语法(AT&T或Intel)中使用字符串指令的显式操作数来编写地址大小覆盖的方法 .
objdump -Mintel
输出相同: