我不理解.code16
或其他.code*
指令的实际用法。我从this question on StackOverflow的答案中了解到,
当某人在其程序集代码中定义.code16
并执行以下操作时:
$ gcc -c -m32 -o main.o main.s
它忽略.code16
,输出程序集将在32位平台上运行。如果有人没有指定-m
标志,它似乎将为gcc配置的标志作为默认设置,这取决于主机。因此,总之,.code*
指令总是被-m
标志所忽略和取代。
如果我理解错了,请有人纠正我,我使用.code16
的情况是什么,因为我总是可以定义使用-m16
和.code*
无论如何都会被忽略,这取决于目标模式。
.code16
(或其他人)是否只打算在数据不能放入16位寄存器时抛出错误,否则,它们将保持休眠状态吗?
发布于 2020-02-02 11:50:56
通常使用.code16
、.code32
或.code64
的唯一原因是当您希望在同一个文件中拥有不同模式的机器代码时,在内核或引导程序中。例如,以实模式(.code16
)启动的引导加载程序可以启用保护模式和跳远(ljmp
)到32位代码段。您可能希望在这段代码之前使用.code32
。
如果这不是你要做的,就不要用它们。
在其他情况下,使用它们只会让你自投罗网,并将16位的机器代码放入32位或64位的ELF可执行文件中,这样您就可以获得运行时故障,而不是在构建时捕获错误。(例如,因为push %eax
在64位模式下无效)。不要将.code32
放在32位程序的顶部;使用一个注释,上面写着与gcc -m32
汇合。
这些指令告诉汇编程序,当它解码这些指令时,CPU将采用什么模式。因此,它知道默认操作数大小和地址大小,以及使用32位或16位寄存器的指令是否需要前缀。
例如,mov %eax, (%ecx)
以32位模式组装到89 01
.
但是在.code16
之后,它组装成67 66 89 01
。
如果然后将其反汇编为32位机器代码,则为67 66 89 01 mov %ax, (%bx,%di)
(因为在16位、32位和64位模式下,内存操作数的ModRM是不同的)。
通常不会手动使用.code16
。您可以使用gcc -m16 foo.c
让GCC在文件顶部插入.code16gcc
,这样您就可以以16位模式运行它,即使它仍然使用32位操作数大小和地址大小(需要一个386兼容的CPU)。
如果您希望将32位或16位机器代码作为数据包含在普通64位程序中,例如,您的程序可以将其写入文件或修改正在运行的进程,您也可以使用.code32
或.code16
。
https://stackoverflow.com/questions/60025609
复制相似问题