- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试关注 this创建二进制文件的教程,但链接器似乎在程序集末尾附加了额外的指令。我假设这是操作系统的拆卸过程。
本教程尝试在 Linux 上编译基本的 32 位 C 程序:
int main() {
}
使用这些命令:
gcc -c test.c
ld -o test -Ttext 0x0 -e main test.o
objcopy -R .note -R .comment -S -O binary test test.bin
ndisasm -b 32 test.bin
我运行的是 64 位 Linux,因此修改了编译步骤如下:
gcc -m32 -c test.c
ld -m elf_i386 -o test -Ttext 0x0 -e main test.o
objcopy -R .note -R .comment -S -O binary test test.bin
ndisasm -b 32 test.bin
预期的输出是:
00000000 55 push ebp
00000001 89E5 mov ebp,esp
00000003 C9 leave
00000004 C3 ret
我的输出如下:
;; START expected output
00000000 55 push bp
00000001 89E5 mov bp,sp
00000003 5D pop bp
00000004 C3 ret
;; END expected output
00000005 0000 add [eax],al
00000007 001400 add [eax+eax],dl
0000000A 0000 add [eax],al
0000000C 0000 add [eax],al
0000000E 0000 add [eax],al
00000010 017A52 add [edx+0x52],edi
00000013 0001 add [ecx],al
00000015 7C08 jl 0x1f
00000017 011B add [ebx],ebx
00000019 0C04 or al,0x4
0000001B 0488 add al,0x88
0000001D 0100 add [eax],eax
0000001F 001C00 add [eax+eax],bl
00000022 0000 add [eax],al
00000024 1C00 sbb al,0x0
00000026 0000 add [eax],al
00000028 D8FF fdivr st7
0000002A FF db 0xff
0000002B FF0500000000 inc dword [dword 0x0]
00000031 41 inc ecx
00000032 0E push cs
00000033 088502420D05 or [ebp+0x50d4202],al
00000039 41 inc ecx
0000003A C50C04 lds ecx,[esp+eax]
0000003D 0400 add al,0x0
0000003F 00 db 0x00
附加指令的用途是什么?如何从目标文件和二进制文件中删除它们?
编辑:
objcopy
参数中的拼写错误(commet -> comment)。更新了反汇编输出。最佳答案
通常,当您在输出文件中看到额外的数据/说明时,问题的根源可能是出现在您预期代码之后的部分。处理此问题的一种方法是查询 ELF 可执行文件以查看它定义了哪些部分。可以只查询带有 -x
参数的部分 OBJDUMP .使用此命令:
objdump -x test
在使用默认参数的 GCC 的大多数现代版本中,应该产生与此类似(不完全)的输出:
test: file format elf32-i386
test
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x00000000
Program Header:
LOAD off 0x00001000 vaddr 0x00000000 paddr 0x00000000 align 2**12
filesz 0x00000040 memsz 0x00000040 flags r-x
STACK off 0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**4
filesz 0x00000000 memsz 0x00000000 flags rw-
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000005 00000000 00000000 00001000 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .eh_frame 00000038 00000008 00000008 00001008 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .comment 0000001d 00000000 00000000 00001040 2**0
CONTENTS, READONLY
SYMBOL TABLE:
00000000 l d .text 00000000 .text
00000008 l d .eh_frame 00000000 .eh_frame
00000000 l d .comment 00000000 .comment
00000000 l df *ABS* 00000000 test.c
00001040 g .eh_frame 00000000 __bss_start
00000000 g F .text 00000005 main
00001040 g .eh_frame 00000000 _edata
00001040 g .eh_frame 00000000 _end
首先应该寻找意想不到的部分。你的OBJCOPY在输出到文件 test.bin
之前,命令使用 -R
从 ELF 对象中删除部分。你做了:
objcopy -R .note -R .comment -S -O binary test test.bin
如果我们排除 .note
和 .comment
部分,上面 OBJDUMP 输出中明显剩下的部分是 .eh_frame
。 .eh_frame
被放置在您的文件 test.bin
中的 .text
部分之后。这包含异常展开信息。这不是实际的说明。 NDISASM将非代码转储为指令,因为二进制文件不区分代码和数据。 NDISASM 盲目地将所有数据转换为指令。
有几种方法可以解决这个问题。您可以像处理其他两个一样排除 .eh_frame
部分。你可以使用:
objcopy -R .note -R .comment -R .eh_frame -S -O binary test test.bin
您还可以告诉 GCC 不要在代码中生成异步异常展开表。这可以通过 GCC 选项完成:
gcc -m32 -c test.c -fno-asynchronous-unwind-tables
这与我的评论有点不同,因为我建议禁用所有异常(exception)。您只需要禁用异步展开表以抑制 .eh_frame
部分。此部分的有用性(或缺乏有用性)在 Stackoverflow answer 中讨论。 . GCC 的手册页 (man gcc
) 讨论了选项 -fasynchronous-unwind-tables
-fasynchronous-unwind-tables
Generate unwind table in DWARF 2 format, if supported by target machine. The table is exact at each
instruction boundary, so it can be used for stack unwinding from asynchronous events (such as debugger or
garbage collector).
这是当今大多数 GCC 的默认设置。使用 -fno-asynchronous-unwind-tables
关闭此功能。
tutorial你链接到的是 2000 年制作的。GCC 及其选项(以及发行版使用的默认值)多年来发生了变化。可能在创建该教程时,异步展开表尚不存在。这可以解释为什么您观察到的输出与教程不同。
关于gcc - 组装结束后附有说明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39456178/
在组装方面,我绝对是个初学者。我尝试找出以下内容的输出应该是什么: Jan dd 255,256 Feb dw 16, 17, 18, 19 Mar db 8, 9, 10, 11 Sub edi,
我正在用 AT&T 语法编写。这个循环应该检查大小写是否在 61-7A ASCII 范围内(这意味着是这个小字母) - 如果不是,则将其转换为空格“”。 change: movb (%esi)
mov eax, ptr_to_num1 ; little endian mov ebx, ptr_to_num2 ; little endian xor ecx, ecx xor edx, edx
我正在制作用于组装的 atoi 函数。 无论我尝试什么都行不通,我也不知道为什么。 有谁知道是什么问题? org 100h mov si, stri ;parameter call atoi
我正在使用 tasm 编写汇编程序。我的任务是编写一个程序,该程序将使用冒泡排序按字母顺序对输入的字符串进行排序。前任。如果你输入“hello”,它应该写成“ehello”。我已经写了请求输入字符串并
假设我的 GPU 包含一个名为 ADT7473 的芯片。 . 我有兴趣从该芯片接收有关我的卡温度的信息。 我的问题是,如何访问这个芯片?是使用 IN/OUT 指令完成的吗? 编辑: 我可能会添加芯片文
我需要在DOS下通过Assembly(intel)+C(c99)绘制QRCode。但看来我的内存太少了。我尝试将图像存储为位数组: image db 11111110b, ... 但无论如何我没有结果
这里有一个简短的问题。我有一个程序集被一些开发人员重复使用,其中包含各种功能,但在技术上分为代表功能逻辑 block 的各种命名空间。 现在,它提供的公共(public) namespace 越少越好
小端: mov eax,4 push dword 0x44434241 mov ebx,1 mov ecx,esp mov edx,4 int 0x80 add esp,4 我不明白为什么它打印 A
是否可以使用元编程技巧来允许在 assembly block 上使用 SFINAE?例如检测处理器上是否有类似“CPUID”的指令:(这不是有效的代码,但说明了我想要实现的目标) // This sh
我有以下形式的项目 - pom.xml - projectA - pom.xml - src/main/ - java - startupScript - projectB
在《微处理器的音乐应用》一书中,作者给出了以下算法,将两个 8 位有符号整数与 16 位有符号结果进行 4 象限相乘: 对原始操作数进行无符号乘法。然后为了更正结果,如果被乘数符号为负,则无符号单精度
我们有一个项目,我们正在 build 大量 Scalatra microservices通过使用 sbt-assembly 打包它们插件,然后使用 sbt-docker 创建 Docker 镜像插入。
所有使用布局的 assemble 用户都知道“{{> body }}”标记了任何使用布局的页面的内容插入点。但是是否可以定义多个插入点,而不是将所有内容都扔到 {{> body }} 所在的位置? 例
我刚开始学习汇编,我没有找到任何有用的内容。 我正在创建一个简单的程序来读取用户输入,基本上: section .bss opA: resw 1 opB: resw 1 section
我目前正在尝试在 bochs 中编译并运行一个简单的引导加载程序。目前,这是我的 bootloader.asm 文件: [BITS 16] [ORG 0x7C00] ;Where the code g
我正在组装一个“simon”游戏,我需要在按钮打开时发出蜂鸣声,蜂鸣声也应该彼此不同。谢谢 最佳答案 您可以使用speaker让您的设计保持简单。 扬声器可让您播放不同频率的方波,it can act
我无法通过任何文档找到问题的答案。 可靠集合通过云的多个节点共享,并且具有名称和持久性。 它们可以通过不同的应用程序共享还是特定于应用程序? 例如,两个不同的 MVC 应用程序对同一帐户托管的可靠字典
嗨,我有一个 SBT 构建文件,用于处理我们组织内的集成测试,测试本身可以工作,我可以单独运行单元和它测试。但是,当使用 sbt-assemble 打包应用程序时,我无法按顺序运行两个测试(unit+
我正在运行一些汇编代码,但我无法弄清楚一行代码的作用。代码是: leaq 0(,%rax,4), %rdx 我知道lea基本上是一种mov指令,但它只移动地址。因此,我们将某些内容的地址移动到%
我是一名优秀的程序员,十分优秀!