- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有以下 C 源文件,其中一些 asm block 通过调用 DOS 系统调用来实现打印和退出例程。
__asm__(
".code16gcc;"
"call dosmain;"
"mov $0x4C, %AH;"
"int $0x21;"
);
void print(char *str)
{
__asm__(
"mov $0x09, %%ah;"
"int $0x21;"
: // no output
: "d"(str)
: "ah"
);
}
void dosmain()
{
// DOS system call expects strings to be terminated by $.
print("Hello world$");
}
链接器脚本文件和构建脚本文件是这样的,
OUTPUT_FORMAT(binary)
SECTIONS
{
. = 0x0100;
.text :
{
*(.text);
}
.data :
{
*(.data);
*(.bss);
*(.rodata);
}
_heap = ALIGN(4);
}
gcc -fno-pie -Os -nostdlib -ffreestanding -m16 -march=i386 \
-Wl,--nmagic,--script=simple_dos.ld simple_dos.c -o simple_dos.com
我习惯于在汇编中构建 .COM 文件,我知道 dos 文件的结构。但是,对于使用 GCC 生成的 .COM 文件,我在末尾得到了一些额外的字节,但我无法弄清楚原因。 (阴影区域内的字节和下面的方框是预期的,其他一切都下落不明)。
[ ]
我的直觉是这些是 GCC 使用的一些静态存储。我认为这可能是由于程序中的字符串所致。因此,我对行 print("Hello world$");
进行了注释,但额外的字节仍然存在。如果有人知道发生了什么并告诉如何防止 GCC 在输出中插入这些字节,那将会有很大的帮助。
此处提供源代码:Github
PS:目标文件也包含这些额外的字节。
最佳答案
由于您使用的是 native 编译器而不是 i686(或 i386)交叉编译器,因此您可以获得大量额外信息。它相当依赖于编译器配置。我建议执行以下操作以删除不需要的代码生成和部分:
-fno-asynchronous-unwind-tables
消除任何 .eh_frame
部分。在这种情况下,这就是在 DOS COM 程序末尾附加不需要的数据的原因。-static
进行构建而不重定位以避免任何形式的动态链接。-Wl
将 --build-id=none
选项传递给链接器,以避免不必要地生成任何 .note.gnu.build- id
部分。.comment
部分。您的构建命令可能如下所示:
gcc -fno-pie -static -Os -nostdlib -fno-asynchronous-unwind-tables -ffreestanding \
-m16 -march=i386 -Wl,--build-id=none,--nmagic,--script=simple_dos.ld simple_dos.c \
-o simple_dos.com
我会将您的链接描述文件修改为:
OUTPUT_FORMAT(binary)
SECTIONS
{
. = 0x0100;
.text :
{
*(.text*);
}
.data :
{
*(.data);
*(.rodata*);
*(.bss);
*(COMMON)
}
_heap = ALIGN(4);
/DISCARD/ : { *(.comment); }
}
除了添加/DISCARD/指令以消除任何 .comment
部分外,我还在 .bss
旁边添加了 *(COMMON)
。两者都是 BSS 部分。我还将它们移到数据部分之后,因为如果它们出现在其他部分之后,它们将不会占用 .COM 文件中的空间。我还将 *(.rodata);
更改为 *(.rodata*);
并将 *(.text);
更改为 * (.text*);
因为 GCC 可以生成以 .rodata
和 .text
开头但具有不同后缀的节名称。
与您询问的问题无关,但很重要。在此内联程序集中:
__asm__(
"mov $0x09, %%ah;"
"int $0x21;"
: // no output
: "d"(str)
: "ah"
);
Int 21h/AH=9h还破坏了 AL。您应该使用 ax
作为 clobber。
由于您是通过寄存器传递数组的地址,因此您还需要添加一个内存
破坏器,以便编译器在您的内联程序集发出之前将整个数组存入内存。约束 "d"(str)
只告诉编译器您将使用指针作为输入,而不是指针指向什么。
如果您在 -O3
处进行了优化编译,您可能会发现程序的以下版本甚至没有您的字符串 "Hello world$"
这是因为这个错误:
__asm__(
".code16gcc;"
"call dosmain;"
"mov $0x4C, %AH;"
"int $0x21;"
);
void print(char *str)
{
__asm__(
"mov $0x09, %%ah;"
"int $0x21;"
: // no output
: "d"(str)
: "ax");
}
void dosmain()
{
char hello[] = "Hello world$";
print(hello);
}
dosmain
的生成代码在堆栈上为字符串分配了空间,但在打印字符串之前从未将字符串放入堆栈:
00000100 <print-0xc>:
100: 66 e8 12 00 00 00 calll 118 <dosmain>
106: b4 4c mov $0x4c,%ah
108: cd 21 int $0x21
10a: 66 90 xchg %eax,%eax
0000010c <print>:
10c: 67 66 8b 54 24 04 mov 0x4(%esp),%edx
112: b4 09 mov $0x9,%ah
114: cd 21 int $0x21
116: 66 c3 retl
00000118 <dosmain>:
118: 66 83 ec 10 sub $0x10,%esp
11c: 67 66 8d 54 24 03 lea 0x3(%esp),%edx
122: b4 09 mov $0x9,%ah
124: cd 21 int $0x21
126: 66 83 c4 10 add $0x10,%esp
12a: 66 c3 retl
如果您更改内联程序集以包含这样的 “内存”
破坏器:
void print(char *str)
{
__asm__(
"mov $0x09, %%ah;"
"int $0x21;"
: // no output
: "d"(str)
: "ax", "memory");
}
生成的代码可能看起来类似于:
00000100 <print-0xc>:
100: 66 e8 12 00 00 00 calll 118 <dosmain>
106: b4 4c mov $0x4c,%ah
108: cd 21 int $0x21
10a: 66 90 xchg %eax,%eax
0000010c <print>:
10c: 67 66 8b 54 24 04 mov 0x4(%esp),%edx
112: b4 09 mov $0x9,%ah
114: cd 21 int $0x21
116: 66 c3 retl
00000118 <dosmain>:
118: 66 57 push %edi
11a: 66 56 push %esi
11c: 66 83 ec 10 sub $0x10,%esp
120: 67 66 8d 7c 24 03 lea 0x3(%esp),%edi
126: 66 be 48 01 00 00 mov $0x148,%esi
12c: 66 b9 0d 00 00 00 mov $0xd,%ecx
132: f3 a4 rep movsb %ds:(%si),%es:(%di)
134: 67 66 8d 54 24 03 lea 0x3(%esp),%edx
13a: b4 09 mov $0x9,%ah
13c: cd 21 int $0x21
13e: 66 83 c4 10 add $0x10,%esp
142: 66 5e pop %esi
144: 66 5f pop %edi
146: 66 c3 retl
Disassembly of section .rodata.str1.1:
00000148 <_heap-0x10>:
148: 48 dec %ax
149: 65 6c gs insb (%dx),%es:(%di)
14b: 6c insb (%dx),%es:(%di)
14c: 6f outsw %ds:(%si),(%dx)
14d: 20 77 6f and %dh,0x6f(%bx)
150: 72 6c jb 1be <_heap+0x66>
152: 64 24 00 fs and $0x0,%al
内联汇编的替代版本,它使用变量通过 a
约束传递子函数 9,并使用 +
将其标记为输入/输出(因为AX 的返回值被破坏)可以这样完成:
void print(char *str)
{
unsigned short int write_fun = (0x09<<8) | 0x00;
__asm__ __volatile__ (
"int $0x21;"
: "+a"(write_fun)
: "d"(str)
: "memory"
);
}
建议:不要使用 GCC 生成 16 位代码。内联汇编是 difficult to get right并且您可能会在低级例程中使用相当数量的它。你可以看看 Smaller C , Bruce's C compiler , 或 Openwatcom C作为替代品。它们都可以生成DOS COM程序。
关于gcc - DOS .COM 文件末尾的额外字节,使用 GCC 编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56368210/
我正在更改链接网址以添加 www.site.com/index.html?s=234&dc=65828 我通过此代码得到的是:site.com/&dc=65828 var target="&dc=65
我在编译过程中收到错误: src/smtp.c:208:1: warning: control reaches end of non-void function [-Wreturn-type] 这是相
这是我的 bootstrap/html 代码: Put email 位置正确,但我希望输入字段的大小延伸到 div 末尾。谁能帮帮我? 最佳答案 只需按百分比指定宽度,如下所示
我正在尝试获取一个像这样的 json 对象: filters = {"filters": myArray}; 并将其附加到 URL 的末尾,使用: this.router.navigate([`/de
这个问题已经有答案了: Remove hash from url (5 个回答) 已关闭 10 年前。 我有一个网站,stepaheadresidents.com ,并且井号 (#) 会自动添加到 u
我有这个代码 $('container a').appendTo('.container'); dzedzdqdqdqzdqdzqdzqdqzdqd Forgot password
为了练习更多 Python 知识,我尝试了 pythonchallenge.com 上的挑战 简而言之,作为第一步,此挑战要求从末尾带有数字的 url 加载 html 页面。该页面包含一行文本,其中有
我对 FS2 很陌生,需要一些有关设计的帮助。我正在尝试设计一个流,它将从底层的 InputStream 中提取 block ,直到结束。这是我尝试过的: import java.io.{File,
我对 FS2 很陌生,需要一些有关设计的帮助。我正在尝试设计一个流,它将从底层的 InputStream 中提取 block ,直到结束。这是我尝试过的: import java.io.{File,
我正在编写一个 ajax 应用程序,并且在 php 脚本中有一个函数: public function expire_user() { $r=array("return"=>'OK');
我正在使用一个QListView,它包装了一个非常简单的列表模型。我想尝试实现类似于某些网页中看到的“无限滚动”的东西。 目前,模型通过最多添加 100 个项目的方法更新(它们取自外部 Web API
运行 cucumber 测试给我以下错误 end of file reached (EOFError) /usr/lib64/ruby/2.0.0/net/protocol.rb:153:in
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我想知道版本命名的具体作用是什么? 喜欢 jquery.js?ver=1.4.4 我的意思是如果我使用像这样的 cdn jquery/1.4.4/jquery.min.js?ver=1.4.4但是另一
" data-fancybox-group="gallery" title="">" alt="" /> 在此代码中 echo $prod['item_image_url'];打印存储在我的表中的图像
我目前使用 Wordpress 作为博客平台,但我想更改为使用 Jekyll 来生成静态页面。在 WordPress 上,我的 URL 使用以下格式: /年/月/日/标题 但我想将其重定向到 /年/月
根据docs这应该是不可能的 Regular expressions cannot be anchored to the beginning or end of a token 尽管如此,它似乎对我有
有没有办法创建 dijit 并将其附加到 div 的末尾?假设我有以下代码: Add Person 我在网上找到了以下代码,但这替换了我的“attendants”div: var personCo
我有这段代码: //execute post (the result will be something like {"result":1,"error":"","id":"4da775
我需要一些函数方面的帮助。 我想编写一个插入链表的函数。但不仅仅是中间,如果必须插入前端或末尾,它也必须起作用。 结构: typedef struct ranklist { i
我是一名优秀的程序员,十分优秀!