bootloader代码应该如何选择反汇编模式?
How should the disassembly mode be chosen for bootloader code?
假设我有一个要调试的引导加载程序汇编代码,它使用 .code16
和 .code32
来为 CPU 的不同模式定义代码,它在 运行 中。此引导加载程序适用的架构是 64 位 (x86) CPU.
现在在反汇编过程中应该使用什么模式(使用objdump、gdb等工具)? i8086
? i386
? x86-64
?
根据我的理解和观察,我们应该根据我们正在分析的代码部分(.code16
、.code32
)使用它们的组合,因为这给出了预期的结果(对我来说) .
例如:
.code16
mov %ax, %bx
mov %ecx, %edx
.code32
mov %eax, %ebx
mov %cx, %dx
这样编译:
$ as -o test.o test.S. #16-bit and 32-bit code packed in 64-bit elf, default 64 since host is 64-bit
16 位模式反汇编CPU。 16位代码段显示正常,32位代码段乱码
$ objdump -m i8086 -d test.o
test.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <.text>:
0: 89 c3 mov %ax,%bx
2: 66 89 ca mov %ecx,%edx
5: 89 c3 mov %ax,%bx
7: 66 89 ca mov %ecx,%edx
正在以 32 位模式分析。现在32位的coe段被完美反汇编了,虽然16位的代码段乱七八糟
$ objdump -m i386 -d test.o
test.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <.text>:
0: 89 c3 mov %eax,%ebx
2: 66 89 ca mov %cx,%dx
5: 89 c3 mov %eax,%ebx
7: 66 89 ca mov %cx,%dx
请确认策略是否完美,否则,请指正混合汇编代码(16、32、64位)反汇编时最好的方法是什么。
您设计的示例不包括可以更改模式的远跳转,因此反汇编是否有效取决于您希望 CPU 对其进行解码的模式。执行将继续通过两个块合并为一个模式。
例如,在Determine your language's version I show all 3 ways to disassemble that block of machine code; all 3 are equally valid and produce different results intentionally. (It's polyglot machine code like )
如果您在实际用例中确实有不同的代码块,大概您想要查看 16 位部分的 16 位反汇编,以及 32 位部分的 32 位反汇编.或者只是阅读源代码。 或者让你的 assembler 生成一个列表,比如 nasm -l /dev/stdout -fbin foo.asm
. 然后你会根据什么模式为每个源代码行得到 "the machine code"你告诉 assembler 到 assemble for.
GAS 也可以使用 as -a
或 gcc -c -Wa,-a
(-Wa 将额外的选项直接传递给 assembler)。
该清单仅包括十六进制机器代码和源代码行(包括注释),不包括 disassembly。因此,如果您使用 .byte
之类的技巧手动编码一条指令,您将看不到 CPU 将如何解释它。为此,请参阅 Ross 的回答或使用调试器。
$ as -a foo.s -o foo.o # still creates an output file as normal
GAS LISTING foo.s page 1
1 .code16
2 0000 89C3 mov %ax, %bx
3 0002 6689CA mov %ecx, %edx # comment
4
5 .code32
6 0005 89C3 mov %eax, %ebx # comment 1
7 0007 6689CA mov %cx, %dx # comment 2
GAS LISTING foo.s page 2
NO DEFINED SYMBOLS
NO UNDEFINED SYMBOLS
左栏是地址。
(我修改了您的源代码以改变间距并添加注释,以仔细检查它只是转储源代码行,而不是反汇编。)
GAS 列表默认为标准输出,-ahls
列表选项 gas man page。没有 -h
"high level source" 用于手写 asm 文件,该选项用于从编译器输出中生成列表,但这很好。列/分页有选项选项,例如 --listing-lhs-width=number
您还可以使用带有内置调试器的仿真器(如 BOCHS)在 CPU 当前处于 的模式下显示反汇编。 BOCHS 了解模式、实模式分段等。 这可能是确保真正执行正确指令的最佳选择。(如果 BOCHS 可以读取调试信息/源代码,您可能需要另一个 window 中的源代码。 )
反汇编程序无法知道什么是 16 位代码或 32 位代码,因此您需要明确地告诉它。例如 objdump:
> objdump -m i8086 --stop-address 0x5 -D test.o
test.o: file format pe-i386
Disassembly of section .text:
00000000 <.text>:
0: 89 c3 mov %ax,%bx
2: 66 89 ca mov %ecx,%edx
> objdump -m i386 --start-address 0x5 -D test.o
test.o: file format pe-i386
Disassembly of section .text:
00000005 <.text+0x5>:
5: 89 c3 mov %eax,%ebx
7: 66 89 ca mov %cx,%dx
a: 90 nop
b: 90 nop
由于您将其与引导加载程序一起使用,因此您可能还想使用 --adjust-vma
选项:
> objdump -m i8086 --adjust-vma 0x7c00 --stop-address 0x7c05 -D t457.o
t457.o: file format pe-i386
Disassembly of section .text:
00007c00 <.text>:
7c00: 89 c3 mov %ax,%bx
7c02: 66 89 ca mov %ecx,%edx
如果您不构建二进制引导加载程序,那么您可能需要考虑将不同的代码类型放入不同的部分,以便于 select 反汇编哪一部分(-j
选项objdump).
其他命令行反汇编程序有类似这些的选项,例如 ndisasm 的 -k
选项。
假设我有一个要调试的引导加载程序汇编代码,它使用 .code16
和 .code32
来为 CPU 的不同模式定义代码,它在 运行 中。此引导加载程序适用的架构是 64 位 (x86) CPU.
现在在反汇编过程中应该使用什么模式(使用objdump、gdb等工具)? i8086
? i386
? x86-64
?
根据我的理解和观察,我们应该根据我们正在分析的代码部分(.code16
、.code32
)使用它们的组合,因为这给出了预期的结果(对我来说) .
例如:
.code16
mov %ax, %bx
mov %ecx, %edx
.code32
mov %eax, %ebx
mov %cx, %dx
这样编译:
$ as -o test.o test.S. #16-bit and 32-bit code packed in 64-bit elf, default 64 since host is 64-bit
16 位模式反汇编CPU。 16位代码段显示正常,32位代码段乱码
$ objdump -m i8086 -d test.o
test.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <.text>:
0: 89 c3 mov %ax,%bx
2: 66 89 ca mov %ecx,%edx
5: 89 c3 mov %ax,%bx
7: 66 89 ca mov %ecx,%edx
正在以 32 位模式分析。现在32位的coe段被完美反汇编了,虽然16位的代码段乱七八糟
$ objdump -m i386 -d test.o
test.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <.text>:
0: 89 c3 mov %eax,%ebx
2: 66 89 ca mov %cx,%dx
5: 89 c3 mov %eax,%ebx
7: 66 89 ca mov %cx,%dx
请确认策略是否完美,否则,请指正混合汇编代码(16、32、64位)反汇编时最好的方法是什么。
您设计的示例不包括可以更改模式的远跳转,因此反汇编是否有效取决于您希望 CPU 对其进行解码的模式。执行将继续通过两个块合并为一个模式。
例如,在Determine your language's version I show all 3 ways to disassemble that block of machine code; all 3 are equally valid and produce different results intentionally. (It's polyglot machine code like
如果您在实际用例中确实有不同的代码块,大概您想要查看 16 位部分的 16 位反汇编,以及 32 位部分的 32 位反汇编.或者只是阅读源代码。 或者让你的 assembler 生成一个列表,比如 nasm -l /dev/stdout -fbin foo.asm
. 然后你会根据什么模式为每个源代码行得到 "the machine code"你告诉 assembler 到 assemble for.
GAS 也可以使用 as -a
或 gcc -c -Wa,-a
(-Wa 将额外的选项直接传递给 assembler)。
该清单仅包括十六进制机器代码和源代码行(包括注释),不包括 disassembly。因此,如果您使用 .byte
之类的技巧手动编码一条指令,您将看不到 CPU 将如何解释它。为此,请参阅 Ross 的回答或使用调试器。
$ as -a foo.s -o foo.o # still creates an output file as normal
GAS LISTING foo.s page 1
1 .code16
2 0000 89C3 mov %ax, %bx
3 0002 6689CA mov %ecx, %edx # comment
4
5 .code32
6 0005 89C3 mov %eax, %ebx # comment 1
7 0007 6689CA mov %cx, %dx # comment 2
GAS LISTING foo.s page 2
NO DEFINED SYMBOLS
NO UNDEFINED SYMBOLS
左栏是地址。
(我修改了您的源代码以改变间距并添加注释,以仔细检查它只是转储源代码行,而不是反汇编。)
GAS 列表默认为标准输出,-ahls
列表选项 gas man page。没有 -h
"high level source" 用于手写 asm 文件,该选项用于从编译器输出中生成列表,但这很好。列/分页有选项选项,例如 --listing-lhs-width=number
您还可以使用带有内置调试器的仿真器(如 BOCHS)在 CPU 当前处于 的模式下显示反汇编。 BOCHS 了解模式、实模式分段等。 这可能是确保真正执行正确指令的最佳选择。(如果 BOCHS 可以读取调试信息/源代码,您可能需要另一个 window 中的源代码。 )
反汇编程序无法知道什么是 16 位代码或 32 位代码,因此您需要明确地告诉它。例如 objdump:
> objdump -m i8086 --stop-address 0x5 -D test.o
test.o: file format pe-i386
Disassembly of section .text:
00000000 <.text>:
0: 89 c3 mov %ax,%bx
2: 66 89 ca mov %ecx,%edx
> objdump -m i386 --start-address 0x5 -D test.o
test.o: file format pe-i386
Disassembly of section .text:
00000005 <.text+0x5>:
5: 89 c3 mov %eax,%ebx
7: 66 89 ca mov %cx,%dx
a: 90 nop
b: 90 nop
由于您将其与引导加载程序一起使用,因此您可能还想使用 --adjust-vma
选项:
> objdump -m i8086 --adjust-vma 0x7c00 --stop-address 0x7c05 -D t457.o
t457.o: file format pe-i386
Disassembly of section .text:
00007c00 <.text>:
7c00: 89 c3 mov %ax,%bx
7c02: 66 89 ca mov %ecx,%edx
如果您不构建二进制引导加载程序,那么您可能需要考虑将不同的代码类型放入不同的部分,以便于 select 反汇编哪一部分(-j
选项objdump).
其他命令行反汇编程序有类似这些的选项,例如 ndisasm 的 -k
选项。