GNU 工具称为 objdump,例如:
objdump -D -b binary -m i8086 <file>
-m i386
或 -Mintel,x86-64
。 i8086
是一种旧架构,将其用于现代代码可能会产生意想不到的结果。此外,现在将 x86-64
指定为 -M
可能是一个好主意,因为许多机器都是 64 位的。将 intel
传递给 -M
会将语法更改为 Intel 样式,而不是您可能想要也可能不想要的默认 AT&T 样式。
为此,我喜欢 ndisasm
。它带有 NASM 汇编器,它是免费和开源的,并包含在大多数 linux 发行版的软件包存储库中。
ndisasm -b16 -o7c00h -a -s7c3eh mbr
说明 - 来自 ndisasm 手册页
-b = 指定 16、32 或 64 位模式。默认为 16 位模式。
-o = 指定文件的名义加载地址。此选项使 ndisasm 获取它在左边距下列出的地址,以及与 PC 相关的跳转和调用的目标地址,右边。
-a = 启用自动(或智能)同步模式,在这种模式下,ndisasm 将尝试通过检查相对跳转的目标地址来猜测应该在哪里执行同步,并将其称为反汇编。
-s = 手动指定同步地址,这样 ndisasm 将不会输出包含地址两侧字节的任何机器指令。因此,从该地址开始的指令将被正确反汇编。
mbr = 要反汇编的文件。
-b specifies 16-, 32- or 64-bit mode. The default is 16-bit mode.
-o is the notional load address for the file. This option causes ndisasm to get the addresses it lists down the left hand margin, and the target addresses of PC-relative jumps and calls, right.
-s specifies a synchronisation address, such that ndisasm will not output any machine instruction which encompasses bytes on both sides of the address. Hence the instruction which starts at that address will be correctly disassembled.
starblue 和 hlovdal 都有部分规范答案。如果你想反汇编原始 i8086 代码,你通常需要 Intel 语法,而不是 AT&T 语法,所以使用:
objdump -D -Mintel,i8086 -b binary -m i386 mbr.bin
objdump -D -Mintel,i386 -b binary -m i386 foo.bin # for 32-bit code
objdump -D -Mintel,x86-64 -b binary -m i386 foo.bin # for 64-bit code
如果您的代码是 ELF(或 a.out(或 (E)COFF)),您可以使用以下简称:
objdump -D -Mintel,i8086 a.out # disassembles the entire file
objdump -d -Mintel,i8086 a.out # disassembles only code sections
对于 32 位或 64 位代码,省略 ,8086
; ELF 标头已包含此信息。
jameslin 建议的 ndisasm
也是一个不错的选择,但 objdump
通常是操作系统自带的,可以处理 GNU binutils 支持的所有架构(GCC 支持的超集),它的输出通常可以输入到 GNU as
中(当然,ndisasm 通常可以输入到 nasm
中)。
Peter Cordes 表示“Agner Fog's objconv 非常好。它将标签放在分支目标上,从而更容易弄清楚代码的作用。它可以反汇编成 NASM、YASM、MASM 或 AT&T (GNU) 语法。”
Multimedia Mike 已经发现了 --adjust-vma
; ndisasm
等效项是 -o
选项。
例如,要反汇编 sh4
代码(我使用 Debian 的一个二进制文件进行测试),请将其与 GNU binutils 一起使用(几乎所有其他反汇编程序都仅限于一个平台,例如带有 ndisasm
和 objconv
的 x86):
objdump -D -b binary -m sh -EL x
-m
是机器,-EL
表示 Little Endian(sh4eb
使用 -EB
代替),这与存在于任一字节序的架构相关。
gcc -O3 -masm=intel -fverbose-asm -S -o- | less
,因为我通常会尝试将 C 源代码调整为编译为好的 asm。
试试这个命令:
sudo dd if=/dev/sda bs=512 count=1 | ndisasm -b16 -o7c00h -
不定期副业成功案例分享
--target
而不是-b
。-D
是“反汇编所有部分的内容”;-b bfdname
或--target=bfdname
将强制读取为指定的目标代码格式(在我们的例子中不是 elf,而是原始二进制文件);-m machine
将指定要使用的体系结构(在我们的文件中没有包含拱信息的标题)。-M options
是反汇编程序的选项;addr16,data16
用于“指定默认地址大小和操作数大小”(在通用 x86 disasm 引擎中将代码视为 i8086 之一)